响应式机制
在Vue文档的深入响应式机制中,提到Vue基于ES5的Object.defineProperty实现了其响应机制,并给出了它的逻辑结构图。
理论上,每一个Vue组件实例拥有一个Watcher实例,其逻辑图为:
挺有意思的,在看源码前,自己照着个图实现了一下。
Watcher
class Watcher{
constructor(el){
this.el = el;
this.data = undefined;
this.dependency = undefined;
}
setData(data,dependency){
this.data = data;
this.dependency = dependency;
this.bind();
this.init();
}
bind(){
let self = this;
Object.keys(self.data).forEach(key => {
let value = self.data[key];
const dm = new DepManager();
dm.register(self);
Object.defineProperty(self.data, key, {
get(){
for(let dep of self.dependency){
dm.collect(dep);
}
return value;
},
set(newValue){
value = newValue;
dm.notify();
}
});
});
}
// 初始化界面渲染效果
init(){
let self = this;
for(let dep of self.dependency){
this.render(dep)
}
}
// 渲染函数
render(func){
// 相应的渲染方法
document.getElementById(this.el).innerHTML=func();
}
}
依赖管理
// 依赖管理者
class DepManager{
constructor(){
// 依赖的方法
this.dependency = [];
// 该属性的相关依赖的订阅者
this.subscribers = [];
}
// 注册订阅者
register(sub){
if(!this.subscribers.includes(sub))
this.subscribers.push(sub);
}
// 收集依赖
collect(dependency){
if(!this.dependency.includes(dependency))
this.dependency.push(dependency);
}
// 通知更新
notify(){
let self = this;
this.dependency.forEach( dep => {
self.subscribers.forEach( sub => sub.render(dep));
});
}
};
实例化
var data = { a:2, b:3 };
var me = new Watcher('test'); // 绑定<div id="test"/>
me.setData(data,[()=>data.a*data.b])