Vue2实现响应式的核心:对象:通过defineProperty劫持(监听/拦截)对象已有属性值的读取和修改数组:通过重写数组来更新数组更新元素的一系列方法,实现元素修改劫持letdata={name:'Liane',age:18}//模拟组件实例let_this={}//Object.defaineProperty()usagefor(letitemindata){Object.defineProperty(_this,item,{//每次获取属性都会触发属性的get()方法get(){returndata[itme]},//每次都会触发这个修改属性值attributeset()methodset(newValue){data[item]=newValue}})}console.log(_this.name)//Liane_this.name='Ann'console.log(_this.name)//Ann1、使用observe函数遍历data的各个属性2.调用Object.defineProperty()对每个att进行响应式处理ribute:使用拦截器属性get()和set()方法进行订阅-发布处理。3、当适合对某个属性进行响应式处理时,会实例化一个Dep实例,使用该属性的组件对应的所有Watcher实例都会存储在subs数组中。当属性被修改时,会通知watcher并调用里面的render函数进行domdiff和update。问题:需要遍历每个需要监控的对象的每个属性,为其添加一个definePropert方法,通过其内部的get()和set()方法来监控和拦截数据,实现起来非常复杂。对象直接添加新属性或删除已有属性,界面不会自动更新,需要使用Vue.set()直接替换元素或通过下标更新长度,界面不会自动更新响应式处理数据和视图未完成解耦Vue3实现响应式核心:通过proxy代理:拦截对数据任意属性的任意操作,包括读写属性值、添加属性、删除属性等,通过reflect反射,动态实现具体操作对代理对象的相应属性执行。//声明一个普通对象,把它变成代理代理响应对象letuser={name:'Liane',age:18}//通过new操作符实例化一个代理对象,newProxy(target,handler)//参数1、target--目标对象//参数2、handler--处理器对象,用于监听数据,以及数据操作letproxyUser=newProxy(user,{//获取目标对象的某个属性值get(target,prop){console.log('getmethodcalled')//通过Reflect反射,对代理对象(目标对象)的相应属性进行具体操作returnReflect.get(target,prop)},//修改属性目标对象的值/向目标对象添加一个新属性set(target,prop,value){console.log('setmethodcalled')returnReflect.set(target,prop,value)},//删除一个目标对象的属性值//Proxy{name:"Liane",age:18}//通过代理对象获取目标对象中的一个属性值console.log(proxyUser.name)//Liane//修改源对象的属性,即代理对象的值也会修改用户.name='Ann'console.log(proxyUser.name)//Ann//通过代理对象proxyUser.name='Rose'console修改目标对象上的属性值。log(user.name)//Rose//通过代理对象,删除目标对象上的属性值deleteproxyUser.nameconsole.log(user)//{age:18}优点:当我们动态添加数据的属性,不需要做任何处理,这个属性已经是响应式的了(不需要循环遍历数据的每个属性,对属性做一个响应式处理,而是直接代理整个数据对象)对数组的任何操作也可以相应触发.
