}
}
}
}
Dep.target = null
const targetStack = []export function pushTarget (_target) {
if (Dep.target) targetStack.push(Dep.target)
Dep.target = _target
}
export function popTarget () {
Dep.target = targetStack.pop()
}
dep 添加prop实现类型的绑定,为什么要这么做那?使用proxy代理后,你假如wahcter对象下的几个元素,此时的deps将同时存在这几个元素,你触发依赖的时候,这些依赖都会执行。因此,通过key值绑定观察事件,触发时,能完成对象的正确触发。
watcher、utils
import { parsePath } from './utils';
import { pushTarget, popTarget } from './dep'
export default class Watcher {
constructor(vm, expOrFn, cb) {
// dep id集合
this.depIds = new Set();
this.vm = vm;
this.getter = parsePath(expOrFn);
this.cb = cb;
this.value = this.get();
}
get () {
pushTarget(this);
let value = this.getter.call(this.vm, this.vm);
popTarget();
return value;
}
update() {
const oldValue = this.value;
this.value = this.get();
this.cb.call(this.vm, this.value, oldValue);
}
addDep (prop, dep) {
const id = dep.id;
if (!this.depIds.has(id)) {
this.depIds.add(id);
dep.addSub(prop, this);
}
}
}utils.js
/**
* 解析简单路径
*/
const bailRE = /[^w.$]/;
export function parsePath (path) {
if (bailRE.test(path)) {
return;
}
const segments = path.split('.');
return function (obj) {
for (let i = 0; i < segments.length; i++) {
if (!obj) return;
obj = obj[segments[i]];
}
return obj;
};
}
/**
* Define a property.
*/
export function def (obj, key, val, enumerable) {
Object.defineProperty(obj, key, {
value: val,
enumerable: !!enumerable,
writable: true,
configurable: true
})
}
/**
* Quick object check - this is primarily used to tell
* Objects from primitive values when we know the value
* is a JSON-compliant type.
*/
export function isObject (obj) {
return obj !== null && typeof obj === 'object'
}
/**
* Check whether an object has the property.
*/
const hasOwnProperty = Object.prototype.hasOwnProperty
export function hasOwn (obj, key) {
return hasOwnProperty.call(obj, key)
}Utils.js/Watchers.js与Vue 2.x类似,这里就不多介绍了。
测试一下
test.js
import Observer from './observer';
import Watcher from './watcher';
let data = {










