目前工作中大约40%的需求都在使用Vue2技术栈。所谓知其所以然,知其所以然更重要,为了更好的使用Vue,更快的查问题,最近学习了一些源码相关的知识。虽然网上有很多关于vue的总结,其中很多都是自己写的,但是不多。欢迎大家一起讨论学习,有问题欢迎指出。响应系统有什么作用?回到最简单的代码:data={text:'hello,world'}constupdateComponent=()=>{console.log('received',data.text);}updateComponent()data.text='hello,liang'//运行结果//接收你好,世界响应系统需要做的事情:一个依赖data数据的函数,当依赖data数据发生变化时,需要重新执行该函数。我们期望的效果:当上面的data.text被修改后,updateComponent函数又被执行了一次。为了实现响应式系统,我们需要做两件事:知道哪些函数依赖于data中的数据,以便在data中的数据发生变化时调用依赖于它的函数。为了实现第一点,我们需要执行函数。保存当前函数,读取数据时再将函数保存到当前数据中。第二点很容易解决,当数据修改时,保存的函数执行一次就可以了。读取和修改数据时需要做一些额外的事情,我们可以通过Object.defineProperty()重写对象属性的get和set函数。响应式数据让我们写一个函数来重写属性的get和set函数。/***在对象上定义一个响应式属性。*/exportfunctiondefineReactive(obj,key,val){constproperty=Object.getOwnPropertyDescriptor(obj,key);//读取可能由用户定义的get和setconstgetter=property&&property.get;constsetter=property&&property.set;//如果没有传入val,则手动赋值if((!getter||setter)&&arguments.length===2){val=obj[key];}Object.defineProperty(obj,key,{enumerable:true,configurable:true,get:functionreactiveGetter(){constvalue=getter?getter.call(obj):val;/**************************************************///1.这里需要保存当前的Executed函数/***************************************************/返回价值;},设置:functionreactiveSetter(newVal){constvalue=getter?getter.call(obj):val;if(setter){setter.call(obj,newVal);}else{val=newVal;}/************************************************///2.执行依赖于当前数据的函数/*************************************************/},});}为了调用更方便,我们将步骤1和步骤2的操作封装在一个Dep类中exportdefaultclassDep{statictarget;//当前正在执行的函数子;//依赖函数constructor(){this.subs=[];//保存所有需要执行的函数}addSub(sub){this.subs.push(sub);}depend(){//当get触发时转到这里if(Dep.target){//委托给Dep.target调用addSubDep.target.addDep(this);}}notify(){for(leti=0,l=this.subs.length;i
