响应式机制
在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'); // 绑定me.setData(data,[()=>data.a*data.b])