一、vue依赖Watcher
Watcher实例就是依赖,接受三个参数,分别为target, expression, callback,target就是监听的对象,expression就是监听对象的某个属性,callback就是这个属性改变时会执行的函数
var uid = 0;
export default class Watcher {
constructor(target, expression, callback) {
console.log('我是Watcher类的构造器');
this.id = uid++;
this.target = target;
// parsePath(expression)返回一个函数,放在getter上,所以getter没有什么特别含义
this.getter = parsePath(expression);
this.callback = callback;
this.value = this.get();
}
update() {
this.run();
}
get() {
// 进入依赖收集阶段。让全局的Dep.target设置为Watcher本身,那么就是进入依赖收集阶段
Dep.target = this;
const obj = this.target;
var value;
// 只要能找,就一直找
try {
// 此时要找到obj里expression这个属性值
value = this.getter(obj);
} finally {zhih1
Dep.target = null;
}
return value;
}
run() {
this.getAndInvoke(this.callback);
}
getAndInvoke(cb) {
const value = this.get();
if (value !== this.value || typeof value == 'object') {
const oldValue = this.value;
this.value = value;
cb.call(this.target, value, oldValue);
}
}
};
二、parsePath函数
在使用依赖watcher时:
new Watcher(data, 'a.b.c', callback)
在这个类中,首先会解析a.b.c,得到所使用的属性,此时需要一个parsePath函数,该函数会返回一个函数(赋值在实例的getter上),并获得所使用的属性,但要注意的是,通过这个函数我们并不知道这个属性属于那个对象,只有通过我们传入一个对象后才知道
function parsePath(str) {
var segments = str.split('.')
return (obj) => {
for(let i = 0; i < segments.length; i++) {
// 若obj不存在,则表示找不到这个属性
if(!obj) return
obj = obj[segments[i]]
}
return obj
}
}