Vue.js3.0響應(yīng)式系統(tǒng)原理_第1頁
Vue.js3.0響應(yīng)式系統(tǒng)原理_第2頁
Vue.js3.0響應(yīng)式系統(tǒng)原理_第3頁
Vue.js3.0響應(yīng)式系統(tǒng)原理_第4頁
Vue.js3.0響應(yīng)式系統(tǒng)原理_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Vue.js3.0響應(yīng)式系統(tǒng)原理Vue.js響應(yīng)式原理回顧*Proxy對(duì)象實(shí)現(xiàn)屬性監(jiān)聽多層屬性嵌套,在訪問屬性過程中處理下一級(jí)屬性默認(rèn)監(jiān)聽動(dòng)態(tài)添加的屬性默認(rèn)監(jiān)聽屬性的刪除操作默認(rèn)監(jiān)聽數(shù)組索引和length屬性可以作為單獨(dú)的模塊使用核心方法reactive/ref/toRefs/computedeffectwatch/watchEffect是vue3runtime.core中實(shí)現(xiàn)的,內(nèi)部使用effect底層函數(shù)track收集依賴trigger觸發(fā)更新響應(yīng)式系統(tǒng)原理ProxyProxy和Reflec是ES6為了操作對(duì)象而提供的新APIproxy中有兩個(gè)需要注意的地方:set和deletePrope

2、rty中需要返回布爾類型的值usestrict/set和deleteProperty中需要返回布爾類型的值/在嚴(yán)格模式下,如果返回false的話會(huì)出現(xiàn)TypeError的異常consttarget=foo:xxx;bar:yyy/Reflect.getPrototypeOf()相當(dāng)于Object.getPrototypeOf()constproxy=newProxy(target,/receive代表當(dāng)前的的Proxy對(duì)象或者繼承Proxy的對(duì)象get(target,key,receiver)/returntargetkey/Reflec反射,代碼運(yùn)行期間獲取對(duì)象中的成員returnRefle

3、ct.get(target,key,receiver),set(target,key,value,receiver)/targetkey=value/Reflect.set設(shè)置成功返回true設(shè)置失敗返回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時(shí),頁面會(huì)報(bào)錯(cuò)-UncaugliitTypeError:dieletePropertyaonprosy:trapreturnedfaIsishiforpropertyfcotatBlprow“htil:37image-20210414080553080.pngProxy和Reflect中使用的receiver指向/Proxy中receiver:Proxy或者繼承Proxy的對(duì)象/Reflect中receiver:如果target對(duì)象中設(shè)置了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時(shí),可以看到this返回的是obj對(duì)象,proxy.foo返回undefinedimage-20210414080743227.png當(dāng)傳遞了receiver時(shí),this指向Proxy對(duì)象image-20210414080825068.png響

6、應(yīng)式系統(tǒng)原理reactive接收一個(gè)參數(shù),判斷這參數(shù)是否是對(duì)象,不是直接返回,只能轉(zhuǎn)換對(duì)象為響應(yīng)式對(duì)象創(chuàng)建攔截器對(duì)象handler,設(shè)置get/set/deleteProperty*返回Proxy對(duì)象/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)測(cè)試set和delete,結(jié)果如下image-20210414082410979.pngreactive實(shí)現(xiàn)思路:定義handler對(duì)象,用于Proxy的第二個(gè)參數(shù)(攔截器對(duì)象)get方法實(shí)現(xiàn)收集依賴*返回target中對(duì)于key的value如果value為對(duì)象,需要再次轉(zhuǎn)為響應(yīng)式對(duì)象set方法中實(shí)現(xiàn)獲取key屬性的

8、值,判斷新舊值是否相同,相同時(shí)返回true不同時(shí),先將target中的key對(duì)應(yīng)的value修改為新值最后觸發(fā)更新deleteProperty方法實(shí)現(xiàn)首先判斷target本身是否存在key刪除target中的key,并返回成功或失敗刪除成功,觸發(fā)更新代碼示例: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)/觸發(fā)更新returnresult,deleteProperty(target,key)consthasKey=hasOwn(target,key)constresult=Reflect.deleteProperty(target,key)if(hasKey&result)/觸發(fā)更新returnresult,returnnewProxy(target,handler)測(cè)試,創(chuàng)建html文件進(jìn)行測(cè)試:Documentimportreactivefrom./reactivity/index.jsconstob

11、j=reactive(name:zs,age:18)=lisideleteobj.ageconsoleog(obj)響應(yīng)式系統(tǒng)原理收集依賴+vity+esm-browser.jsimage-20210415080133182.pngtarg&tMapnewW&akMapOdep5MapnewMapQ目標(biāo)對(duì)象depnewSet()目標(biāo)對(duì)象的屬性名稱effect的函數(shù)image-20210414082624298.png依賴收集過程中會(huì)創(chuàng)建3個(gè)集合,分別是targetMap、depsMap和deptargetMap作用是記錄目標(biāo)對(duì)象和一個(gè)字典(depsMap),使用WeakMap弱引用,當(dāng)目標(biāo)對(duì)象

12、失去引用之后,可以銷毀targetMap的值是depsMap,depsMap的key是目標(biāo)對(duì)象的屬性名稱,值是一個(gè)set集合depdep中存儲(chǔ)的是effect函數(shù),因?yàn)榭梢远啻握{(diào)用一個(gè)effect,在effect中訪問同一個(gè)屬性,這時(shí)該屬性會(huì)收集多次依賴,對(duì)應(yīng)多個(gè)effect函數(shù)通過這種結(jié)構(gòu),可以存儲(chǔ)目標(biāo)對(duì)象,目標(biāo)對(duì)象屬性,以及屬性對(duì)應(yīng)的effect函數(shù)個(gè)屬性可能對(duì)應(yīng)多個(gè)函數(shù),當(dāng)觸發(fā)更新時(shí),在這個(gè)結(jié)構(gòu)中根據(jù)目標(biāo)對(duì)象屬性找到effect函數(shù)然后執(zhí)行收集依賴的track函數(shù)內(nèi)部,首先根據(jù)當(dāng)前targetMap對(duì)象找到depsMap,如果沒找到要給當(dāng)前對(duì)象創(chuàng)建一個(gè)depsMap,并添加到target

13、Map中,如果找到了再根據(jù)當(dāng)前使用的屬性在depsMap找到對(duì)應(yīng)的dep,dep中存儲(chǔ)的是effect函數(shù),如果沒有找到時(shí),為當(dāng)前屬性創(chuàng)建對(duì)應(yīng)的dep集合,并且存儲(chǔ)到depsMap中,如果找到當(dāng)前屬性對(duì)應(yīng)的dep集合,就把當(dāng)前的effect函數(shù)存儲(chǔ)到集合中effect方法實(shí)現(xiàn)實(shí)現(xiàn)思路:effect接收函數(shù)作為參數(shù)執(zhí)行函數(shù)并返回響應(yīng)式對(duì)象去收集依賴,收集依賴過程中將callback存儲(chǔ)起來,需要在后面的track函數(shù)中能夠訪問到這里的callback依賴收集完畢設(shè)置activeEffect為null代碼實(shí)現(xiàn):letactiveEffect=nullexportfunctioneffect(cal

14、lback)activeEffect=callbackcallback。/訪問響應(yīng)式對(duì)象屬性,去收集依賴activeEffect=nulltrack方法實(shí)現(xiàn)實(shí)現(xiàn)思路:track接收兩個(gè)參數(shù),目標(biāo)對(duì)象target和需要跟蹤的屬性key內(nèi)部需要將target存儲(chǔ)到targetMap中,targetMap定義在外面,除了track使用外trigger函數(shù)也要使用activeEffect不存在直接返回,否則需要在targetMap中根據(jù)當(dāng)前target找depsMap判斷是否找到depsMap,因?yàn)閠arget可能還沒有收集依賴未找到,為當(dāng)前target創(chuàng)建depsMap去存儲(chǔ)對(duì)應(yīng)的鍵和dep對(duì)象,并

15、添加到targetMap中根據(jù)屬性查找對(duì)應(yīng)的dep對(duì)象,dep是個(gè)集合,存儲(chǔ)effect函數(shù)判斷是否存在,未找到時(shí)創(chuàng)建新的dep集合并添加到depsMap中將effect函數(shù)添加到dep集合中在收集依賴的get中調(diào)用這個(gè)函數(shù)代碼實(shí)現(xiàn):此時(shí),整個(gè)依賴收集過程已經(jīng)完成trigger方法實(shí)現(xiàn)依賴收集完成后需要觸發(fā)更新實(shí)現(xiàn)思路:參數(shù)target和key根據(jù)target在targetMap中找至】depsMap未找到時(shí),直接返回再根據(jù)key找對(duì)應(yīng)的dep集合,effect函數(shù)如果dep有值,遍歷dep集合執(zhí)行每一個(gè)effect函數(shù)在set和deleteProperty中觸發(fā)更新代碼實(shí)現(xiàn):exportfu

16、nctiontrigger(target,key)constdepsMap=targetMap.get(target)if(!depsMap)returnconstdep=depsMap.get(key)if(dep)dep.forEach(effect)=effect()依賴收集和觸發(fā)更新代碼完成,創(chuàng)建html文件進(jìn)行測(cè)試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)打開瀏覽器控制臺(tái),可以看到輸出結(jié)果如下卜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響應(yīng)式系統(tǒng)原理refrefvsreactiveref可以把基本數(shù)據(jù)類型數(shù)據(jù),轉(zhuǎn)成響應(yīng)式對(duì)象ref返回的對(duì)象,重新賦值成對(duì)象也是響應(yīng)式的reactive返回的對(duì)象,重新賦值丟失響應(yīng)式*reactive返回的對(duì)象不可以解構(gòu)實(shí)現(xiàn)原理:判斷raw是否是ref創(chuàng)建的對(duì)象,如果是的話直接返回判斷raw是否是對(duì)象,如果是對(duì)象調(diào)用reactive創(chuàng)建響應(yīng)式對(duì)象,否則返回原始值創(chuàng)建ref對(duì)象并返回,標(biāo)識(shí)是否是ref對(duì)象,這個(gè)對(duì)象只有value屬性,并且這個(gè)value屬性具有set和getget中調(diào)用track收集依

19、賴,收集依賴的對(duì)象是剛創(chuàng)建的r對(duì)象,屬性是value,也就是當(dāng)訪問對(duì)象中的值,返回的是內(nèi)部的變量valueset中判斷新舊值是否相等,不相等時(shí)將新值存儲(chǔ)到raw中,并調(diào)用convert處理raw,最終把結(jié)果存儲(chǔ)到value中,如果給value重新賦值為一個(gè)對(duì)象依然是響應(yīng)式的,當(dāng)raw是對(duì)象時(shí)convert里調(diào)用reactive轉(zhuǎn)換為響應(yīng)式對(duì)象最后觸發(fā)更新代碼實(shí)現(xiàn):,returnrexportfunctionref(raw)/判斷raw是否是ref創(chuàng)建的對(duì)象,如果是的話直接返回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)創(chuàng)建html文件進(jìn)行測(cè)試: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)打開控制臺(tái)可以看到輸出結(jié)果和上面的相同響應(yīng)式系統(tǒng)原理toRefs實(shí)現(xiàn)思路:接收參數(shù)proxy,判斷參數(shù)是否為reactive創(chuàng)建的對(duì)象,如果不是發(fā)出警告判斷傳入?yún)?shù),如果是數(shù)組創(chuàng)建長度是Iength的數(shù)組,否則返回空對(duì)象,因?yàn)閭魅氲膒roxy可能是響應(yīng)式數(shù)組或響應(yīng)式對(duì)象接著遍歷proxy對(duì)象的所有屬性,如果是數(shù)組遍歷索引,將每一個(gè)屬性都轉(zhuǎn)換為類似ref返回的對(duì)象創(chuàng)建toProxyRef函數(shù),接收proxy和key,創(chuàng)建對(duì)象并最終返回對(duì)象(類似ref返回的對(duì)象)創(chuàng)建標(biāo)識(shí)屬

22、性_v_isRef,這里的get中不需要收集依賴,因?yàn)檫@里訪問的是響應(yīng)式對(duì)象,當(dāng)訪問屬性時(shí),內(nèi)部的getter回去收集依賴,set不需要觸發(fā)更新,調(diào)用代理對(duì)象內(nèi)部的set觸發(fā)更新調(diào)用toProxyRef,將所有屬性轉(zhuǎn)換并存儲(chǔ)到ret中toRefs將reactive返回的對(duì)象的所有屬性都轉(zhuǎn)換成一個(gè)對(duì)象,所以當(dāng)對(duì)響應(yīng)式對(duì)象進(jìn)行解構(gòu)的時(shí)候,解構(gòu)出的每一個(gè)屬性都是對(duì)象,而對(duì)象是引用傳遞,所以解構(gòu)的屬性依然是響應(yīng)式的代碼實(shí)現(xiàn):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創(chuàng)建html進(jìn)行測(cè)試:importreactive,effect,toRefsfrom./reactivity/index.jsfunctionuseProduct()constproduct=reactive(name:iPhone,price:5000,count:3)returntoRefs(produ

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論