最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解vue3?響應(yīng)式的實(shí)現(xiàn)原理

 更新時(shí)間:2022年06月13日 09:33:05   作者:Bigger  
Vue.js?3.0?為了解決?Object.defineProperty?的這些缺陷,使用?Proxy?API?重寫了響應(yīng)式部分,并獨(dú)立維護(hù)和發(fā)布整個(gè)?reactivity?庫(kù),這篇文章主要介紹了vue3?響應(yīng)式的實(shí)現(xiàn)原理,需要的朋友可以參考下

核心設(shè)計(jì)思想

除了組件化,Vue.js 另一個(gè)核心設(shè)計(jì)思想就是響應(yīng)式。它的本質(zhì)是當(dāng)數(shù)據(jù)變化后會(huì)自動(dòng)執(zhí)行某個(gè)函數(shù),映射到組件的實(shí)現(xiàn)就是,當(dāng)數(shù)據(jù)變化后,會(huì)自動(dòng)觸發(fā)組件的重新渲染。響應(yīng)式是 Vue.js 組件化更新渲染的一個(gè)核心機(jī)制。

Vue.js 2.x 響應(yīng)式

我們先來(lái)回顧一下 Vue.js 2.x 響應(yīng)式實(shí)現(xiàn)的部分: 它在內(nèi)部通過(guò) Object.defineProperty API 劫持?jǐn)?shù)據(jù)的變化,在數(shù)據(jù)被訪問(wèn)的時(shí)候收集依賴,然后在數(shù)據(jù)被修改的時(shí)候通知依賴更新。

在 Vue.js 2.x 中,Watcher 就是依賴,有專門針對(duì)組件渲染的 render watcher。這里有兩個(gè)流程,首先是依賴收集流程,組件在 render 的時(shí)候會(huì)訪問(wèn)模板中的數(shù)據(jù),觸發(fā) getter 把 render watcher 作為依賴收集,并和數(shù)據(jù)建立聯(lián)系;然后是派發(fā)通知流程,當(dāng)我對(duì)這些數(shù)據(jù)修改的時(shí)候,會(huì)觸發(fā) setter,通知 render watcher 更新,進(jìn)而觸發(fā)了組件的重新渲染。

Object.defineProperty API 的一些缺點(diǎn):

不能監(jiān)聽對(duì)象屬性新增和刪除;
初始化階段遞歸執(zhí)行 Object.defineProperty 帶來(lái)的性能負(fù)擔(dān)。

在 Vue.js 2.x 中,data 中定義的數(shù)據(jù),Vue.js 內(nèi)部在組件初始化的過(guò)程中會(huì)把它變成響應(yīng)式,這是一個(gè)相對(duì)黑盒的過(guò)程,用戶通常不會(huì)感知到。

Vue.js 3.x 響應(yīng)式

Vue.js 3.0 為了解決 Object.defineProperty 的這些缺陷,使用 Proxy API 重寫了響應(yīng)式部分,并獨(dú)立維護(hù)和發(fā)布整個(gè) reactivity 庫(kù)。

也就是在 Vue.js 3.0 中,是用 reactive 這個(gè)有魔力的函數(shù),把數(shù)據(jù)變成了響應(yīng)式。

reactive 內(nèi)部通過(guò) createReactiveObject 函數(shù)把 target 變成了一個(gè)響應(yīng)式對(duì)象,這個(gè)函數(shù)主要做了以下幾件事情:

1、函數(shù)首先判斷 target 是不是數(shù)組或者對(duì)象類型,如果不是則直接返回。所以**原始數(shù)據(jù) target 必須是對(duì)象或者數(shù)組**。
2、如果對(duì)一個(gè)已經(jīng)是響應(yīng)式的對(duì)象再次執(zhí)行 reactive,還應(yīng)該返回這個(gè)響應(yīng)式對(duì)象。
3、如果對(duì)同一個(gè)原始數(shù)據(jù)多次執(zhí)行 reactive ,那么會(huì)返回相同的響應(yīng)式對(duì)象。
4、使用 canObserve 函數(shù)對(duì) target 對(duì)象做一進(jìn)步限制。
5、通過(guò) Proxy API 劫持 target 對(duì)象,把它變成響應(yīng)式。
6、給原始數(shù)據(jù)打個(gè)標(biāo)識(shí)。

響應(yīng)式的實(shí)現(xiàn)方式無(wú)非就是劫持?jǐn)?shù)據(jù),Vue.js 3.0 的 reactive API 就是通過(guò) Proxy 劫持?jǐn)?shù)據(jù),而且由于 Proxy 劫持的是整個(gè)對(duì)象,所以我們可以檢測(cè)到任何對(duì)對(duì)象的修改,彌補(bǔ)了 Object.defineProperty API 的不足。

依賴收集:get 函數(shù)

依賴收集發(fā)生在數(shù)據(jù)訪問(wèn)的階段

get 函數(shù)主要做了四件事情:

1、對(duì)特殊的 key 做了代理
2、通過(guò) Reflect.get 方法求值
3、執(zhí)行 track 函數(shù)收集依賴(最核心)
4、對(duì)計(jì)算的值 res 進(jìn)行判斷,如果它也是數(shù)組或?qū)ο?,則遞歸執(zhí)行 reactive 把 res 變成響應(yīng)式對(duì)象。

Object.defineProperty 是在初始化階段,即定義劫持對(duì)象的時(shí)候就已經(jīng)遞歸執(zhí)行了,而 Proxy 是在對(duì)象屬性被訪問(wèn)的時(shí)候才遞歸執(zhí)行下一步 reactive,這其實(shí)是一種延時(shí)定義子對(duì)象響應(yīng)式的實(shí)現(xiàn),在性能上會(huì)有較大的提升

收集的依賴就是數(shù)據(jù)變化后執(zhí)行的副作用函數(shù)

每次 track ,就是把當(dāng)前激活的副作用函數(shù) activeEffect 作為依賴,然后收集到 target 相關(guān)的 depsMap 對(duì)應(yīng) key 下的依賴集合 dep 中。

派發(fā)通知:set 函數(shù)

派發(fā)通知發(fā)生在數(shù)據(jù)更新的階段

set 函數(shù)主要就做兩件事情:

1、通過(guò) Reflect.set 求值
2、通過(guò) trigger 函數(shù)派發(fā)通知(最核心),并依據(jù) key 是否存在于 target 上來(lái)確定通知類型,即新增還是修改。

trigger 函數(shù)主要做了四件事情:

1、通過(guò) targetMap 拿到 target 對(duì)應(yīng)的依賴集合 depsMap;
2、創(chuàng)建運(yùn)行的 effects 集合;
3、根據(jù) key 從 depsMap 中找到對(duì)應(yīng)的 effect 添加到 effects 集合;
4、遍歷 effects 執(zhí)行相關(guān)的副作用函數(shù)。

每次 trigger 函數(shù)就是根據(jù) target 和 key ,從 targetMap 中找到相關(guān)的所有副作用函數(shù)遍歷執(zhí)行一遍。

依賴收集和派發(fā)通知的過(guò)程中都提到副作用函數(shù),依賴收集過(guò)程中我們把 activeEffect(當(dāng)前激活副作用函數(shù))作為依賴收集。

總結(jié)

其實(shí) Vue.js 3.0 在響應(yīng)式的實(shí)現(xiàn)思路和 Vue.js 2.x 差別并不大,主要就是 劫持?jǐn)?shù)據(jù)的方式改成用 Proxy 實(shí)現(xiàn) , 以及收集的依賴由 watcher 實(shí)例變成了組件副作用渲染函數(shù) 。

源碼參考

由于源碼太多,本文就不展示,可直接去: github.com/vuejs/core

packages/reactivity/src/baseHandlers.ts
packages/reactivity/src/effect.ts
packages/reactivity/src/reactive.ts
packages/reactivity/src/baseHandlers.ts
packages/reactivity/src/ref.ts

到此這篇關(guān)于vue3 響應(yīng)式的實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)vue3 響應(yīng)式原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

永安市| 西吉县| 南雄市| 扶风县| 金山区| 双柏县| 明光市| 治多县| 清涧县| 岑巩县| 鄂州市| 科技| 富源县| 双柏县| 始兴县| 沧州市| 永年县| 广州市| 克什克腾旗| 葫芦岛市| 江口县| 石台县| 达州市| 河北省| 若尔盖县| 沛县| 长阳| 合作市| 澳门| 资中县| 左权县| 北碚区| 安仁县| 盐亭县| 资源县| 贡山| 邻水| 阳山县| 南靖县| 阿勒泰市| 武山县|