vue3響應(yīng)式Proxy與Reflect的理解及基本使用實(shí)例詳解
正文
在第四章中,作者講述了Vue.js中響應(yīng)式系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn),這一塊其實(shí)是整個(gè)框架的基石,也是MVVM中,ViewModel(VM)的重要組成部分。 其實(shí)在上一章中我已經(jīng)感覺(jué)很難了,有一些操作作者也只是幾筆帶過(guò),卻很值得我們思考。這一張中,我們將目光著重于響應(yīng)式數(shù)據(jù)本身,來(lái)完善上一章中我們的demo。
理解Proxy與Reflect
vue3的響應(yīng)式離不開(kāi)Proxy
,說(shuō)到Proxy
則離不開(kāi)Reflect
.這兩個(gè)對(duì)象是ES6新增的對(duì)象,同時(shí)在編程領(lǐng)域,他們也代表著2種設(shè)計(jì)模式,即代理與反射。設(shè)計(jì)模式都是后話,等我學(xué)會(huì)了也一定寫(xiě)一篇文章分享一下??.
Proxy
Proxy
可以理解成,在目標(biāo)對(duì)象之前架設(shè)一層“攔截”,外界對(duì)該對(duì)象的訪問(wèn),都必須經(jīng)過(guò)這層攔截,而我們就可以通過(guò)這層攔截去改變目標(biāo)對(duì)象的內(nèi)容或者行為,或者叫過(guò)濾和控制。這個(gè)詞本意就是代理,好比一個(gè)代理人站在神奇,我們所有行為都會(huì)被他過(guò)濾,可能我們說(shuō)的話,經(jīng)過(guò)代理人一說(shuō),意思就變了。
ES6 原生提供 Proxy 構(gòu)造函數(shù),用來(lái)生成 Proxy 實(shí)例。
var proxy = new Proxy(target, handler);
其中target
表示要代理的那個(gè)對(duì)象,handler
則是表示我們需要攔截的行為,這里直接放一張阮一峰的截圖。
Reflect
Reflect
中文譯為:反射。如果說(shuō)Proxy
是有一個(gè)代理人站在身前面,幫你攔截并處理一些行為,那么Reflect
就是你身后的一面鏡子,它能看見(jiàn)真實(shí)的自己。
而你自己,就是一個(gè)類或者對(duì)象,或者一個(gè)函數(shù),只要是js中存在的,都能被Proxy
和 Reflect
處理。
它的操作和Proxy
正好相反,但卻一一對(duì)應(yīng)。比如我們獲取對(duì)象中一個(gè)屬性。
const obj = {foo:1} const a = Reflect.get(obj, 'foo')
這一小節(jié)主要是介紹了Proxy與Reflect,后面會(huì)有一個(gè)應(yīng)用老告訴你為什么Proxy與Reflect與響應(yīng)式數(shù)據(jù)息息相關(guān)。
實(shí)踐示例
看完了Proxy
與Reflect
的基本使用之后,我們實(shí)踐一下。
我們?cè)?jīng)寫(xiě)過(guò)這樣的代碼
const reactive = (object)=>{ return new Proxy(object,{ get(target,key){ track(target,key) return target[key] } set(target,key, newVal){ target[key] = newVal trigger(target,key) return true } }) }
其實(shí)就是用Proxy
代理了對(duì)象讀和取操作,在讀的時(shí)候收集依賴,在取的時(shí)候觸發(fā)響應(yīng)??雌饋?lái)似乎沒(méi)有問(wèn)題,那么我們?cè)僭嚴(yán)^續(xù)往下寫(xiě)
const obj = { a:1, get b(){ return this.a } } const data = reactive(obj) effect(()=>{ console.log(data.b) }) setTimeOut(()=>{ data.b++ },500)
這里我們沒(méi)有用一般的對(duì)象寫(xiě)法,而是通過(guò)訪問(wèn)器為它新增了一個(gè)b屬性.之后,我們先把這個(gè)對(duì)象轉(zhuǎn)換為響應(yīng)式對(duì)象,再給他們?cè)O(shè)定一個(gè)響應(yīng)式的回調(diào),然后在冬天改變他的值,理論上這時(shí)候應(yīng)該會(huì)執(zhí)行副作用函數(shù),但是實(shí)際上呢,根本不會(huì)執(zhí)行。
我們回顧一下之前寫(xiě)的reactive
方法,在里面返回的是target[key]
,當(dāng)我們的target是obj,key是b的時(shí)候,那個(gè)this會(huì)是誰(shuí)呢?因?yàn)閠arget是原始對(duì)象,也就是obj,根據(jù)誰(shuí)調(diào)用是誰(shuí)的原則,這個(gè)this也就指向了obj。obj是響應(yīng)式對(duì)象嗎,顯然不是,那個(gè)b也就永遠(yuǎn)不會(huì)執(zhí)行副作用函數(shù),響應(yīng)式就失效了。
這里其實(shí)就是this的指向問(wèn)題,你可能會(huì)說(shuō)一般人怎么會(huì)用getter去賦值屬性呢,但是這個(gè)作為一個(gè)簡(jiǎn)單的case,甚至都算不上邊界,我們需要解決它。
解決的方法也很簡(jiǎn)單,就是通過(guò)Reflect
。這也是為什么我說(shuō)Proxy
與Reflect
就是焦不離孟 孟不離焦. 我們的reactive,get的時(shí)候,加入第三個(gè)參數(shù)receiver
get(target,key){ track(target,key,receiver) return Reflect.get(target,key,receiver) }
我這里理解的是,receiver
就相當(dāng)于函數(shù)的bind
方法,它改變的this的執(zhí)行,當(dāng)我們同過(guò)Reflect
讀取值的時(shí)候,this的指向被改為receiver
,而Reflect
時(shí)的receiver
又是Proxy
中的入?yún)?,它?zhí)行了這個(gè)Proxy
,從而把前文中this的指向由obj改為data,這樣響應(yīng)式就不會(huì)丟失了。
下一章中,作者會(huì)深入的介紹一下Proxy
和一些相關(guān)的標(biāo)準(zhǔn)。
以上就是vue3響應(yīng)式Proxy與Reflect的理解及基本使用實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于vue3響應(yīng)式Proxy Reflect的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue路由跳轉(zhuǎn)到新頁(yè)面實(shí)現(xiàn)置頂
這篇文章主要介紹了vue路由跳轉(zhuǎn)到新頁(yè)面實(shí)現(xiàn)置頂問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05Vue條件循環(huán)判斷+計(jì)算屬性+綁定樣式v-bind的實(shí)例
今天小編就為大家分享一篇Vue條件循環(huán)判斷+計(jì)算屬性+綁定樣式v-bind的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Vue?動(dòng)畫(huà)效果、過(guò)渡效果的示例代碼
這篇文章主要介紹了Vue?動(dòng)畫(huà)效果、過(guò)渡效果,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04vue使用lodop打印控件實(shí)現(xiàn)瀏覽器兼容打印的方法
這篇文章主要介紹了vue使用lodop打印控件實(shí)現(xiàn)瀏覽器兼容打印的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02vue本地模擬服務(wù)器請(qǐng)求mock數(shù)據(jù)的方法詳解
這篇文章主要給大家介紹了關(guān)于vue本地模擬服務(wù)器請(qǐng)求mock數(shù)據(jù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03