双向绑定完整代码(https://github.com/mfaying/si...双向绑定对于vue.js来说很重要,也是一种框架的特点那么如何实现数据的双向绑定呢?本文将基于vue.js2.x版本来讲解双向绑定的原理,Object和Array的实现原理是不同的,这个文章讲解了Object双向绑定的原理,要实现双向绑定必须要能够监听数据的取值和赋值,幸好JavaScript原生提供了Object.defineProperty来监听。functiondefineReactive(data,key,val){if(typeofval==="object"){newObserver(val);}letdep=newDep();Object.defineProperty(data,key,{enumerable:true,configurable:true,get:function(){dep.depend();returnval;},set:function(newVal){if(val===newVal){return;}val=newVal;dep.notify();}});}我们在get中收集依赖并触发er中的依赖项。依赖收集在dep中,定义如下:exportdefaultclassDep{constructor(){this.subs=[];}addSub(sub){this.subs.push(sub);}removeSub(sub){remove(this.subs,sub);}depend(){if(window.target){this.addSub(window.target);}}notify(){constsubs=this.subs.slice();for(leti=0,l=subs.length;i-1){返回arr.splice(索引,1);}}}Dep解耦了依赖管理的逻辑。它的原理也很简单,基于数组来管理依赖。那么依赖被通知了,它会做什么呢?答案是守望者。Watcher可以理解为任何需要触发操作的数据变化,比如视图更新。import{parsePath}from"./util";exportdefaultclassWatcher{constructor(vm,expOrFn,cb){this.vm=vm;this.getter=parsePath(expOrFn);这个.cb=cb;this.value=this.get();}get(){window.target=this;letvalue=this.getter.call(this.vm,this.vm);window.target=undefined;返回值;}update(){constoldValue=this.value;this.value=this.get();this.cb.call(this.vm,this.value,oldValue);}}Watcher和Dep可以通过一个公共变量window.target实现依赖的自动收集。最后,我们需要一个Observer类,它可以将普通对象完全转换为响应式数据。不管键在对象的哪个位置,因为它在实现中使用了递归。classObserver{constructor(value){this.value=value;如果(!Array.isArray(value)){this.walk(value);}}walk(obj){constkeys=Object.keys(obj);for(leti=0;i{console.log("watcher");});//执行后打印watcherwindow.data.a.b=1;参考《深入浅出Vue.js》完整代码(https://github.com/mfaying/si...