Vue3?Reactive響應(yīng)式原理邏輯詳解
前言
本篇文章主要講解vue
響應(yīng)式原理的邏輯,也就是vue
怎么從最開(kāi)始一步步推導(dǎo)出響應(yīng)式的結(jié)構(gòu)框架。 先從頭構(gòu)建一個(gè)簡(jiǎn)單函數(shù)推導(dǎo)出Vue3的Reactive原理,最后再進(jìn)行源碼的驗(yàn)證。
一、怎么實(shí)現(xiàn)變量變化
怎么實(shí)現(xiàn)變量變化,相關(guān)依賴的結(jié)果也跟著變化
當(dāng)原本price=5
變?yōu)?code>price=20后total
應(yīng)該變?yōu)?code>40,但是實(shí)際total
并不會(huì)改變。 解決辦法可以這樣,當(dāng)變量改變了,重新計(jì)算一次,那么結(jié)果就會(huì)改變?yōu)樽钚碌慕Y(jié)果。
如果需要重新計(jì)算,我們需要將total
語(yǔ)句存儲(chǔ)為一個(gè)函數(shù),才能實(shí)現(xiàn)依賴的變量改變就進(jìn)行一次依賴項(xiàng)計(jì)算。這里就用effect
表示函數(shù)名。
來(lái),試一下:
??,實(shí)現(xiàn)了變量price
改變,依賴變量price quantity
的變量total
也發(fā)生改變。
下一步,我們要解決的問(wèn)題是:應(yīng)該怎么把effect
存儲(chǔ)起來(lái),讓代碼更加有通用性,而不是一直復(fù)寫(xiě)effect
,分離出其他的功能的函數(shù)各司其職,也就是大家常說(shuō)的解耦。
二、怎么實(shí)現(xiàn)變量變化
怎么實(shí)現(xiàn)變量變化,變量改變后就取出effect執(zhí)行
用什么存儲(chǔ)effect
呢?當(dāng)然是用Set,因?yàn)镾et會(huì)過(guò)濾出重復(fù)的元素,所以能夠保證存儲(chǔ)在Set中的函數(shù)不是重復(fù)的。 這里定義一個(gè)存儲(chǔ)effect
依賴的變量為dep = new Set()
,定義track
函數(shù)表示存儲(chǔ)的過(guò)程。 定義trigger
函數(shù)用以取出dep
中相關(guān)的effect
函數(shù)執(zhí)行(這里定義的函數(shù)與Vue3源碼同名同意義)。
effect
: 會(huì)影響結(jié)果的函數(shù)(要實(shí)現(xiàn)響應(yīng)式的依賴語(yǔ)句)track
:保存所有的effecttrigger
: 當(dāng)變量改變重新執(zhí)行代碼
??,解耦之后代碼結(jié)構(gòu)更清晰了。
下面需要解決的一個(gè)問(wèn)題:一個(gè)object通常有多個(gè)屬性,比如product = { price: 5, quantity: 2 }
,在保存依賴時(shí)只創(chuàng)建了一個(gè)dep
的集合,應(yīng)該給price
和quantity
都創(chuàng)建dep
,因?yàn)?code>total的最終結(jié)果依賴這兩個(gè)屬性,其中任何一個(gè)改變都要觸發(fā)trigger
函數(shù)。創(chuàng)建了兩個(gè)dep
就需要一個(gè)容器將dep
存儲(chǔ)起來(lái)。
三、將多個(gè)dep存儲(chǔ)在Map中
因?yàn)椴煌膶傩悦凶约簩?duì)應(yīng)的dep
,所以我們用Map結(jié)構(gòu)(鍵值對(duì)形式)來(lái)保存不同dep
。
??,一個(gè)object的多個(gè)屬性依賴問(wèn)題解決,更具有通用性了。
下一個(gè)問(wèn)題是:不可能只有一個(gè)對(duì)象,多個(gè)對(duì)象又怎么辦?let product = { price: 5, quantity: 2 }
let user = { firstName: "Joe", lastName: "Smith" }
,比如兩個(gè)對(duì)象的時(shí)候就需要進(jìn)一步修改上面的代碼了。
四、將多個(gè)object的depsMap繼續(xù)存儲(chǔ)起來(lái)
這里用WeakMap
數(shù)據(jù)結(jié)構(gòu)去存儲(chǔ)多個(gè)需要響應(yīng)式的object的depsMap
。WeakMap
的基本使用和Map
差不多,只不過(guò)WeakMap
只接受對(duì)象為鍵值,而depsMap
是一個(gè)Map
結(jié)構(gòu)剛好(必須是)是對(duì)象類型。targetMap
作為存儲(chǔ)多個(gè)depsMap
的容器名。
??,到這里已經(jīng)基本實(shí)現(xiàn)了通用性的響應(yīng)式代碼了,但是還有最后一個(gè)問(wèn)題就是:我們的代碼都需要手動(dòng)執(zhí)行(自己添加trigger
運(yùn)行),不能自動(dòng)運(yùn)行。怎么讓它能夠自動(dòng)檢測(cè)變量改變,然后自動(dòng)修改結(jié)果呢?
五、核心
通過(guò)Reflect和Proxy解決自執(zhí)行問(wèn)題
在JavaScript中,自動(dòng)檢測(cè)變量不就是get
、自動(dòng)修改變量不就是set
嗎?在Vue2.x版本中用ES5的Obeject.defineProperty()
自帶的getter/setter
去解決這個(gè)問(wèn)題。ES6中Proxy
也能解決這個(gè)問(wèn)題,但是Proxy
不兼任IE瀏覽器,當(dāng)時(shí)大家還討論過(guò)說(shuō)不知道尤大怎么去考慮這個(gè)問(wèn)題,現(xiàn)在問(wèn)題的答案就是——不考慮。也就是根本不考慮IE兼不兼容????。
Proxy
就是代理的意思,任何對(duì)真實(shí)數(shù)據(jù)的操作它都能攔截并且代理操作,也就是說(shuō)Object
上一些能實(shí)現(xiàn)的方法,Proxy
也能實(shí)現(xiàn)。Proxy
使用語(yǔ)法是new Proxy(target, hanler)
,handler
是你想實(shí)現(xiàn)什么樣的代理功能配置。 而Reflect
就更神奇了,它的作用是取代Object
類上的一些方法讓Obeject
類更純粹的代表一個(gè)類,不要附加太多方法在上面,比如a in obj
表示判斷obj
中是否有a
,在Reflect
中用Reflect.has(a)
比較語(yǔ)義化的方式就可以代替之前的方法。
正是因?yàn)檫@樣,Proxy
和Reflect
就對(duì)應(yīng)上了,都有Object
上的方法。
稍微封裝一下我們的函數(shù),名叫Reactive
??,至此,Vue3基本的響應(yīng)式原理就解析完了。
六、源碼解析(TypeScript)
return
了createReactiveObject
函數(shù),所以去看createReactiveObject
。
前面的代碼都是判斷各種情況,我們就看最后幾行
const observed = new Proxy( target, collectionTypes.has(target.constructor) ? collectionHandlers : baseHandlers )
可以看到Proxy
的handler
為collectionHandlers
或者 baseHandlers
,繼續(xù)選擇一個(gè)看一看。
在 baseHandlers
中可以看到導(dǎo)出了get/set/deleteProperty
等屬性配置:
我們看一下set
:
和我們之前的邏輯差不多,只不過(guò)真正實(shí)現(xiàn)就很復(fù)雜,因?yàn)橛泻芏鄰?fù)雜條件需要去處理。
其他的get
等方法也一樣,做了很多條件判斷處理,完善了每一種會(huì)出現(xiàn)的情況。
到此這篇關(guān)于Vue3 Reactive響應(yīng)式原理邏輯詳解的文章就介紹到這了,更多相關(guān)Vue3 Reactive響應(yīng)式 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3.0?setup中使用vue-router問(wèn)題
這篇文章主要介紹了vue3.0?setup中使用vue-router問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10vue@cli3項(xiàng)目模板怎么使用public目錄下的靜態(tài)文件
這篇文章主要介紹了vue@cli3項(xiàng)目模板怎么使用public目錄下的靜態(tài)文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07詳解vue中v-on事件監(jiān)聽(tīng)指令的基本用法
這篇文章主要介紹了詳解vue中v-on事件監(jiān)聽(tīng)指令的基本用法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07Vue快速實(shí)現(xiàn)通用表單驗(yàn)證的示例代碼
這篇文章主要介紹了Vue快速實(shí)現(xiàn)通用表單驗(yàn)證的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01淺析vue-router中params和query的區(qū)別
這篇文章主要介紹了vue-router中params和query的區(qū)別,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12Vue?transition組件簡(jiǎn)單實(shí)現(xiàn)數(shù)字滾動(dòng)
這篇文章主要為大家介紹了Vue?transition組件簡(jiǎn)單實(shí)現(xiàn)數(shù)字滾動(dòng)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09