Vue.js3.0响应式系统原理_第1页
Vue.js3.0响应式系统原理_第2页
Vue.js3.0响应式系统原理_第3页
Vue.js3.0响应式系统原理_第4页
Vue.js3.0响应式系统原理_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Vue.js3.0响应式系统原理Vue.js响应式原理回顾*Proxy对象实现属性监听多层属性嵌套,在访问属性过程中处理下一级属性默认监听动态添加的属性默认监听属性的删除操作默认监听数组索引和length属性可以作为单独的模块使用核心方法reactive/ref/toRefs/computedeffectwatch/watchEffect是vue3runtime.core中实现的,内部使用effect底层函数track收集依赖trigger触发更新响应式系统原理ProxyProxy和Reflec是ES6为了操作对象而提供的新APIproxy中有两个需要注意的地方:set和deletePrope

2、rty中需要返回布尔类型的值usestrict/set和deleteProperty中需要返回布尔类型的值/在严格模式下,如果返回false的话会出现TypeError的异常consttarget=foo:xxx;bar:yyy/Reflect.getPrototypeOf()相当于Object.getPrototypeOf()constproxy=newProxy(target,/receive代表当前的的Proxy对象或者继承Proxy的对象get(target,key,receiver)/returntargetkey/Reflec反射,代码运行期间获取对象中的成员returnRefle

3、ct.get(target,key,receiver),set(target,key,value,receiver)/targetkey=value/Reflect.set设置成功返回true设置失败返回falsereturnReflect.set(target,key,value,receiver),deleteProperty(target,key)/deletetargetkeyreturnReflect.deleteProperty(target,key)proxy.foo=zzz/deleteproxy.foo1uzzpzFUdizFQFZFUdzFQpAFUd*-*已中丿人1?1j

4、*-*-i*-1如果set和deleteProperty返回false时,页面会报错-UncaugliitTypeError:dieletePropertyaonprosy:trapreturnedfaIsishiforpropertyfcotatBlprow“htil:37image-20210414080553080.pngProxy和Reflect中使用的receiver指向/Proxy中receiver:Proxy或者继承Proxy的对象/Reflect中receiver:如果target对象中设置了getter,getter中的this指向receiverconstobj=getfo

5、o()consoleog(this)returnthis.bar,constproxy=newProxy(obj,get(target,key,receiver)if(key=bar)returnvalue-barreturnReflect.get(target,key,receiver),)consoleog(proxy.foo)不传递receiver时,可以看到this返回的是obj对象,proxy.foo返回undefinedimage-20210414080743227.png当传递了receiver时,this指向Proxy对象image-20210414080825068.png响

6、应式系统原理reactive接收一个参数,判断这参数是否是对象,不是直接返回,只能转换对象为响应式对象创建拦截器对象handler,设置get/set/deleteProperty*返回Proxy对象/reactivily/index.jsconstisObject=(val)=val!=null&typeofval=objectexportfunctionreactive(target)if(!isObject(target)returnconsthandler=get(target,key,receiver)consoleog(get,key,target),set(target,key,

7、value,receiver)consoleog(set,key,value)returnvalue,deleteProperty(target,key)consoleog(delete,key)returntarget,returnnewProxy(target,handler)测试set和delete,结果如下image-20210414082410979.pngreactive实现思路:定义handler对象,用于Proxy的第二个参数(拦截器对象)get方法实现收集依赖*返回target中对于key的value如果value为对象,需要再次转为响应式对象set方法中实现获取key属性的

8、值,判断新旧值是否相同,相同时返回true不同时,先将target中的key对应的value修改为新值最后触发更新deleteProperty方法实现首先判断target本身是否存在key删除target中的key,并返回成功或失败删除成功,触发更新代码示例:constisObject=(val)=val!=null&typeofval=objectconstconvert=(val)=(isObject(val)?reactive(val):val)consthasOwnProperty=Ototype.hasOwnPropertyconsthasOwn=(target,key)=hasOw

9、nProperty.call(target,key)exportfunctionreactive(target)if(!isObject(target)returnconsthandler=get(target,key,receiver)/收集依赖constvalue=Reflect.get(target,key,receiver)returnconvert(value),set(target,key,value,receiver)constoldValue=Reflect.get(target,key,receiver)letresult=trueif(oldValue!=value)let

10、result=Reflect.set(target,key,value,receiver)/触发更新returnresult,deleteProperty(target,key)consthasKey=hasOwn(target,key)constresult=Reflect.deleteProperty(target,key)if(hasKey&result)/触发更新returnresult,returnnewProxy(target,handler)测试,创建html文件进行测试:Documentimportreactivefrom./reactivity/index.jsconstob

11、j=reactive(name:zs,age:18)=lisideleteobj.ageconsoleog(obj)响应式系统原理收集依赖+vity+esm-browser.jsimage-20210415080133182.pngtarg&tMapnewW&akMapOdep5MapnewMapQ目标对象depnewSet()目标对象的属性名称effect的函数image-20210414082624298.png依赖收集过程中会创建3个集合,分别是targetMap、depsMap和deptargetMap作用是记录目标对象和一个字典(depsMap),使用WeakMap弱引用,当目标对象

12、失去引用之后,可以销毁targetMap的值是depsMap,depsMap的key是目标对象的属性名称,值是一个set集合depdep中存储的是effect函数,因为可以多次调用一个effect,在effect中访问同一个属性,这时该属性会收集多次依赖,对应多个effect函数通过这种结构,可以存储目标对象,目标对象属性,以及属性对应的effect函数个属性可能对应多个函数,当触发更新时,在这个结构中根据目标对象属性找到effect函数然后执行收集依赖的track函数内部,首先根据当前targetMap对象找到depsMap,如果没找到要给当前对象创建一个depsMap,并添加到target

13、Map中,如果找到了再根据当前使用的属性在depsMap找到对应的dep,dep中存储的是effect函数,如果没有找到时,为当前属性创建对应的dep集合,并且存储到depsMap中,如果找到当前属性对应的dep集合,就把当前的effect函数存储到集合中effect方法实现实现思路:effect接收函数作为参数执行函数并返回响应式对象去收集依赖,收集依赖过程中将callback存储起来,需要在后面的track函数中能够访问到这里的callback依赖收集完毕设置activeEffect为null代码实现:letactiveEffect=nullexportfunctioneffect(cal

14、lback)activeEffect=callbackcallback。/访问响应式对象属性,去收集依赖activeEffect=nulltrack方法实现实现思路:track接收两个参数,目标对象target和需要跟踪的属性key内部需要将target存储到targetMap中,targetMap定义在外面,除了track使用外trigger函数也要使用activeEffect不存在直接返回,否则需要在targetMap中根据当前target找depsMap判断是否找到depsMap,因为target可能还没有收集依赖未找到,为当前target创建depsMap去存储对应的键和dep对象,并

15、添加到targetMap中根据属性查找对应的dep对象,dep是个集合,存储effect函数判断是否存在,未找到时创建新的dep集合并添加到depsMap中将effect函数添加到dep集合中在收集依赖的get中调用这个函数代码实现:此时,整个依赖收集过程已经完成trigger方法实现依赖收集完成后需要触发更新实现思路:参数target和key根据target在targetMap中找至】depsMap未找到时,直接返回再根据key找对应的dep集合,effect函数如果dep有值,遍历dep集合执行每一个effect函数在set和deleteProperty中触发更新代码实现:exportfu

16、nctiontrigger(target,key)constdepsMap=targetMap.get(target)if(!depsMap)returnconstdep=depsMap.get(key)if(dep)dep.forEach(effect)=effect()依赖收集和触发更新代码完成,创建html文件进行测试importreactive,effectfrom./reactivity/index.jsconstproduct=reactive(name:iPhone,price:5000,count:3)lettotal=0effect()=total=product.price

17、*product.count)consoleog(total)product.price=4000consoleog(total)product.count=1consoleog(total)打开浏览器控制台,可以看到输出结果如下卜Pr-EJQ1flTOFStfr%阳亡92-efFert-du.htnl!Sfl-lie:!.htl:25卜Rrowyfranc?pries:430E,cou/itrJJfl-2-effct-Me,htnljM取工-七疽応呎-riera?.hfril;2-f.卜ftr-Giryfranc?prieei粵能$rountrTJ淀弋申口-i1efc:i.fitril:四&

18、2-effect-deino.htnl;29image-20210416084313137.png响应式系统原理refrefvsreactiveref可以把基本数据类型数据,转成响应式对象ref返回的对象,重新赋值成对象也是响应式的reactive返回的对象,重新赋值丢失响应式*reactive返回的对象不可以解构实现原理:判断raw是否是ref创建的对象,如果是的话直接返回判断raw是否是对象,如果是对象调用reactive创建响应式对象,否则返回原始值创建ref对象并返回,标识是否是ref对象,这个对象只有value属性,并且这个value属性具有set和getget中调用track收集依

19、赖,收集依赖的对象是刚创建的r对象,属性是value,也就是当访问对象中的值,返回的是内部的变量valueset中判断新旧值是否相等,不相等时将新值存储到raw中,并调用convert处理raw,最终把结果存储到value中,如果给value重新赋值为一个对象依然是响应式的,当raw是对象时convert里调用reactive转换为响应式对象最后触发更新代码实现:,returnrexportfunctionref(raw)/判断raw是否是ref创建的对象,如果是的话直接返回if(isObject(raw)&raw._v_isRef)returnletvalue=convert(raw)con

20、str=_v_isRef:true,getvalue()track(r,value)returnvalue,setvalue(newValue)if(newValue!=value)raw=newValuevalue=convert(raw)trigger(r,value)创建html文件进行测试:importreactive,effect,reffrom./reactivity/index.jsconstprice=ref(5000)constcount=ref(3)lettotal=0effect()=total=price.value*count.value)consoleog(tota

21、l)price.value=4000consoleog(total)count.value=1consoleog(total)打开控制台可以看到输出结果和上面的相同响应式系统原理toRefs实现思路:接收参数proxy,判断参数是否为reactive创建的对象,如果不是发出警告判断传入参数,如果是数组创建长度是Iength的数组,否则返回空对象,因为传入的proxy可能是响应式数组或响应式对象接着遍历proxy对象的所有属性,如果是数组遍历索引,将每一个属性都转换为类似ref返回的对象创建toProxyRef函数,接收proxy和key,创建对象并最终返回对象(类似ref返回的对象)创建标识属

22、性_v_isRef,这里的get中不需要收集依赖,因为这里访问的是响应式对象,当访问属性时,内部的getter回去收集依赖,set不需要触发更新,调用代理对象内部的set触发更新调用toProxyRef,将所有属性转换并存储到ret中toRefs将reactive返回的对象的所有属性都转换成一个对象,所以当对响应式对象进行解构的时候,解构出的每一个属性都是对象,而对象是引用传递,所以解构的属性依然是响应式的代码实现:exportfunctiontoRefs(proxy)constret=proxyinstanceofArray?newArray(proxyength):for(constkey

23、inproxy)retkey=toProxyRef(proxy,key)returnretfunctiontoProxyRef(proxy,key)constr=_v_isRef:true,getvalue()returnproxykey,setvalue(newValue)proxykey=newValue,returnr创建html进行测试:importreactive,effect,toRefsfrom./reactivity/index.jsfunctionuseProduct()constproduct=reactive(name:iPhone,price:5000,count:3)returntoRefs(produ

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论