面试题 vue2 Object.definProperty响应式原理( 二 )

class Dep (){static target = nullconstructor(){this.subs=[];}addSubs(watcher){this.subs.push(watcher)}notify(newVal){for(let i = 0; i < this.subs.length; i++){this.subs[i].update(newVal); }}}

作为连接和的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
观察者类,它做的事情就是观察数据的变更,它会调用data中对应属性的get方法触发依赖收集,并在数据变更后执行相应的更新
let uid = 0;class Watcher{// vm即一个vue对象,key要观察的属性,cb是观测到数据变化后需要做的操作,通常是指dom变更constructor(vm,key,cb){this.vm = vm;this.uid = uid++;this.cb = cb;// 调用get触发依赖收集之前,把自身赋值给Dep.taget静态变量Dep.target=this;// 触发对象上代理的get方法,执行get添加依赖this.value=http://www.kingceram.com/post/vm.$data[key];//用完即清空Dep.target=null;}// 在调用set触发Dep的notify时要执行的update函数,用于响应数据变化执行run函数即dom变更update(newVal){// 值发生变化才变更if(this.value !== newVal){this.value = newVal;this.run()}}// 执行DOM更新等操作run(){this.cb(this.value);}}
通过以上的代码我们就实现了一个去除了模板编译的简易版的Vue,我们用简单化模拟dom的变更
//======测试=======let data={message:'hello',num:0}let app=new Vue({data:data});//模拟数据监听new Watcher(app,'message',function(value){//模拟dom变更console.log('message 引起的dom变更--->',value); // world})new Watcher(app,'num',function(value){//模拟dom变更console.log('num 引起的dom变更--->',value); // 100})data.message='world';data.num=100;
总结
1、实现一个监听器 :对数据对象进行遍历,包括子属性对象的属性,利用 .() 对属性都加上和。这样的话,给这个对象的某个值赋值,就会触发 ,那么就能监听到了数据变化 。并且可以拿到最新值通知订阅者 。
2、实现一个订阅者 : 订阅者是和之间通信的桥梁 ,主要的任务是订阅中的属性值变化的消息,当收到属性值变化的消息时,触发解析器中对应的更新函数 。
3、实现一个解析器 :解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新 。
【面试题vue2 Object.definProperty响应式原理】4、实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 ,对监听器和 订阅者进行统一管理 。