




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、Vue.js3.0響應式系統(tǒng)原理Vue.js響應式原理回顧*Proxy對象實現(xiàn)屬性監(jiān)聽多層屬性嵌套,在訪問屬性過程中處理下一級屬性默認監(jiān)聽動態(tài)添加的屬性默認監(jiān)聽屬性的刪除操作默認監(jiān)聽數(shù)組索引和length屬性可以作為單獨的模塊使用核心方法reactive/ref/toRefs/computedeffectwatch/watchEffect是vue3runtime.core中實現(xiàn)的,內部使用effect底層函數(shù)track收集依賴trigger觸發(fā)更新響應式系統(tǒng)原理ProxyProxy和Reflec是ES6為了操作對象而提供的新APIproxy中有兩個需要注意的地方:set和deletePrope
2、rty中需要返回布爾類型的值usestrict/set和deleteProperty中需要返回布爾類型的值/在嚴格模式下,如果返回false的話會出現(xiàn)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、應式系統(tǒng)原理reactive接收一個參數(shù),判斷這參數(shù)是否是對象,不是直接返回,只能轉換對象為響應式對象創(chuàng)建攔截器對象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實現(xiàn)思路:定義handler對象,用于Proxy的第二個參數(shù)(攔截器對象)get方法實現(xiàn)收集依賴*返回target中對于key的value如果value為對象,需要再次轉為響應式對象set方法中實現(xiàn)獲取key屬性的
8、值,判斷新舊值是否相同,相同時返回true不同時,先將target中的key對應的value修改為新值最后觸發(fā)更新deleteProperty方法實現(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)測試,創(chuàng)建html文件進行測試:Documentimportreactivefrom./reactivity/index.jsconstob
11、j=reactive(name:zs,age:18)=lisideleteobj.ageconsoleog(obj)響應式系統(tǒng)原理收集依賴+vity+esm-browser.jsimage-20210415080133182.pngtarg&tMapnewW&akMapOdep5MapnewMapQ目標對象depnewSet()目標對象的屬性名稱effect的函數(shù)image-20210414082624298.png依賴收集過程中會創(chuàng)建3個集合,分別是targetMap、depsMap和deptargetMap作用是記錄目標對象和一個字典(depsMap),使用WeakMap弱引用,當目標對象
12、失去引用之后,可以銷毀targetMap的值是depsMap,depsMap的key是目標對象的屬性名稱,值是一個set集合depdep中存儲的是effect函數(shù),因為可以多次調用一個effect,在effect中訪問同一個屬性,這時該屬性會收集多次依賴,對應多個effect函數(shù)通過這種結構,可以存儲目標對象,目標對象屬性,以及屬性對應的effect函數(shù)個屬性可能對應多個函數(shù),當觸發(fā)更新時,在這個結構中根據(jù)目標對象屬性找到effect函數(shù)然后執(zhí)行收集依賴的track函數(shù)內部,首先根據(jù)當前targetMap對象找到depsMap,如果沒找到要給當前對象創(chuàng)建一個depsMap,并添加到target
13、Map中,如果找到了再根據(jù)當前使用的屬性在depsMap找到對應的dep,dep中存儲的是effect函數(shù),如果沒有找到時,為當前屬性創(chuàng)建對應的dep集合,并且存儲到depsMap中,如果找到當前屬性對應的dep集合,就把當前的effect函數(shù)存儲到集合中effect方法實現(xiàn)實現(xiàn)思路:effect接收函數(shù)作為參數(shù)執(zhí)行函數(shù)并返回響應式對象去收集依賴,收集依賴過程中將callback存儲起來,需要在后面的track函數(shù)中能夠訪問到這里的callback依賴收集完畢設置activeEffect為null代碼實現(xiàn):letactiveEffect=nullexportfunctioneffect(cal
14、lback)activeEffect=callbackcallback。/訪問響應式對象屬性,去收集依賴activeEffect=nulltrack方法實現(xiàn)實現(xiàn)思路:track接收兩個參數(shù),目標對象target和需要跟蹤的屬性key內部需要將target存儲到targetMap中,targetMap定義在外面,除了track使用外trigger函數(shù)也要使用activeEffect不存在直接返回,否則需要在targetMap中根據(jù)當前target找depsMap判斷是否找到depsMap,因為target可能還沒有收集依賴未找到,為當前target創(chuàng)建depsMap去存儲對應的鍵和dep對象,并
15、添加到targetMap中根據(jù)屬性查找對應的dep對象,dep是個集合,存儲effect函數(shù)判斷是否存在,未找到時創(chuàng)建新的dep集合并添加到depsMap中將effect函數(shù)添加到dep集合中在收集依賴的get中調用這個函數(shù)代碼實現(xiàn):此時,整個依賴收集過程已經(jīng)完成trigger方法實現(xiàn)依賴收集完成后需要觸發(fā)更新實現(xiàn)思路:參數(shù)target和key根據(jù)target在targetMap中找至】depsMap未找到時,直接返回再根據(jù)key找對應的dep集合,effect函數(shù)如果dep有值,遍歷dep集合執(zhí)行每一個effect函數(shù)在set和deleteProperty中觸發(fā)更新代碼實現(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文件進行測試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響應式系統(tǒng)原理refrefvsreactiveref可以把基本數(shù)據(jù)類型數(shù)據(jù),轉成響應式對象ref返回的對象,重新賦值成對象也是響應式的reactive返回的對象,重新賦值丟失響應式*reactive返回的對象不可以解構實現(xiàn)原理:判斷raw是否是ref創(chuàng)建的對象,如果是的話直接返回判斷raw是否是對象,如果是對象調用reactive創(chuàng)建響應式對象,否則返回原始值創(chuàng)建ref對象并返回,標識是否是ref對象,這個對象只有value屬性,并且這個value屬性具有set和getget中調用track收集依
19、賴,收集依賴的對象是剛創(chuàng)建的r對象,屬性是value,也就是當訪問對象中的值,返回的是內部的變量valueset中判斷新舊值是否相等,不相等時將新值存儲到raw中,并調用convert處理raw,最終把結果存儲到value中,如果給value重新賦值為一個對象依然是響應式的,當raw是對象時convert里調用reactive轉換為響應式對象最后觸發(fā)更新代碼實現(xiàn):,returnrexportfunctionref(raw)/判斷raw是否是ref創(chuàng)建的對象,如果是的話直接返回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文件進行測試: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ǒng)原理toRefs實現(xiàn)思路:接收參數(shù)proxy,判斷參數(shù)是否為reactive創(chuàng)建的對象,如果不是發(fā)出警告判斷傳入?yún)?shù),如果是數(shù)組創(chuàng)建長度是Iength的數(shù)組,否則返回空對象,因為傳入的proxy可能是響應式數(shù)組或響應式對象接著遍歷proxy對象的所有屬性,如果是數(shù)組遍歷索引,將每一個屬性都轉換為類似ref返回的對象創(chuàng)建toProxyRef函數(shù),接收proxy和key,創(chuàng)建對象并最終返回對象(類似ref返回的對象)創(chuàng)建標識屬
22、性_v_isRef,這里的get中不需要收集依賴,因為這里訪問的是響應式對象,當訪問屬性時,內部的getter回去收集依賴,set不需要觸發(fā)更新,調用代理對象內部的set觸發(fā)更新調用toProxyRef,將所有屬性轉換并存儲到ret中toRefs將reactive返回的對象的所有屬性都轉換成一個對象,所以當對響應式對象進行解構的時候,解構出的每一個屬性都是對象,而對象是引用傳遞,所以解構的屬性依然是響應式的代碼實現(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進行測試: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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 新解讀《CB-T 429 - 1999單爪錨》新解讀
- 化學●海南卷丨2022年海南省普通高中學業(yè)水平選擇性考試高考化學真題試卷及答案
- 路基人字行骨架防護施工方案
- 基坑開挖工藝流程
- 北師大版(2019) 必修第三冊 Unit 9 Learning Lesson 2 Language Learning Tips課件(內嵌音頻)
- 基于雙球模型改進的眼動追蹤算法研究
- 浙江省麗水市2022-2023學年高二下學期普通高中期末教學質量檢測化學試題(含答案)
- 汽車傳感器與檢測技術電子教案:地磁方位傳感器
- 物理中考一輪復習教案 第三講 熔化和凝固、升華和凝華、水循環(huán)
- 倉庫擴容打折活動方案
- 北歐電力市場組織架構以及交易組織流程
- 患者跌倒的預防及管理課件
- 高院民一庭負責人答記者問:最高院《關于審理城鎮(zhèn)房屋租賃合同糾紛案件具體應用法律若干問題的解釋》
- 體檢報告單入職體檢模板
- 工作計劃及進度表
- 鋪麻醉床技術操作評分標準
- 管道焊接及焊縫外觀檢查記錄表
- 回油管夾片的沖壓工藝與模具設計
- 個體化健康教育
- 《白內障》ppt課件
- Resume(簡歷英文版)
評論
0/150
提交評論