欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文帶你了解vue3.0響應(yīng)式

 更新時(shí)間:2021年09月01日 17:12:22   作者:JonnyLan  
Vue3.0相比較于之前的版本更快、更小、更易于維護(hù)、更貼近原生、對(duì)開(kāi)發(fā)者更友好,本文就Vue3.0進(jìn)行詳細(xì)介紹,需要了解的小伙伴可以參考一下這篇文章

我們知道Vue 2.0是利用Ojbect.defineProperty對(duì)對(duì)象的已有屬性值的讀取和修改進(jìn)行劫持,但是這個(gè)API不能監(jiān)聽(tīng)對(duì)象屬性的新增和刪除,此外為了深度劫持對(duì)象的內(nèi)部屬性,必須在初始化的時(shí)候?qū)?nèi)部屬性進(jìn)行遞歸調(diào)用Ojbect.defineProperty,這就造成了一個(gè)性能上的消耗。為了解決這些問(wèn)題,Vue 3.0利用Proxy重寫了響應(yīng)式邏輯并且優(yōu)化了相關(guān)性能。

使用案例

我們先來(lái)個(gè)示例看下Vue 3.0的響應(yīng)式API的寫法:

案例

changePerson能改變響應(yīng)式數(shù)據(jù)person的值,person值的變化會(huì)觸發(fā)組件重新渲染而更新DOM

這里我們可以看到Vue 3.0的使用中,開(kāi)發(fā)者利用reactive函數(shù)自己去確定哪些數(shù)據(jù)為響應(yīng)式數(shù)據(jù),這樣就可以避免一些不必要的響應(yīng)式的性能消耗。例如案例中我們就不需要讓nowIndex成為響應(yīng)式數(shù)據(jù)。(當(dāng)然Vue 2.0也可以在data函數(shù)外定義數(shù)據(jù),這樣也是非響應(yīng)式數(shù)據(jù))

我們接下來(lái)看看reactive函數(shù)的實(shí)現(xiàn)原理!

reactive API相關(guān)的流程

 reactive

reactive

代碼說(shuō)明:

  • 1.如果目標(biāo)對(duì)象target是readonly對(duì)象,直接返回目標(biāo)對(duì)象,因?yàn)閞eadonly對(duì)象不能設(shè)置成響應(yīng)式對(duì)象
  • 2.調(diào)用createReactiveObject函數(shù)繼續(xù)流程。

createReactiveObject 創(chuàng)建響應(yīng)式對(duì)象

createReactiveObject

代碼說(shuō)明:

  • 1.如果目標(biāo)對(duì)象不是數(shù)據(jù)或者對(duì)象,則直接返回對(duì)象,在開(kāi)發(fā)環(huán)境給出錯(cuò)誤警告提示。
  • 2.如果target已經(jīng)是一個(gè)Proxy對(duì)象,則直接返回target, (target['__v_raw']設(shè)計(jì)非常巧妙:如果targetProxy對(duì)象,target['__v_raw']觸發(fā)get方法,在緩存對(duì)象reactiveMap中查找是否target對(duì)象的Proxy對(duì)象是否等于target自身)。這里處理了一個(gè)例外,如果是給響應(yīng)式對(duì)象執(zhí)行readonly函數(shù)則需要繼續(xù)。
  • 3.在reactiveMap中查找是否已經(jīng)有了對(duì)應(yīng)的Proxy對(duì)象,則直接返回對(duì)應(yīng)的Proxy對(duì)象。
  • 4.確保只有特定的數(shù)據(jù)能變成響應(yīng)式,否則直接返回target。響應(yīng)式白名單如下所示:

1.target沒(méi)有被執(zhí)行過(guò)markRaw方法,或者說(shuō)target對(duì)象沒(méi)有__v_skip屬性值或者__v_skip屬性的值為false;

2.target不能是不可擴(kuò)展對(duì)象,即target沒(méi)有被執(zhí)行過(guò)preventExtensions,sealfreeze這些方法;

3.targetObject或者Array;

4.targetMap,Set,WeakMap,WeakSet;

  • 5.通過(guò)使用Proxy函數(shù)劫持target對(duì)象,返回的結(jié)果即為響應(yīng)式對(duì)象了。這里的處理函數(shù)會(huì)根據(jù)target對(duì)象不同而不同(這兩個(gè)函數(shù)都是參數(shù)傳入的):

1.Object或者Array的處理函數(shù)是collectionHandlers;

2.Map,Set,WeakMap,WeakSet的處理函數(shù)是baseHandlers;

  • 6.將響應(yīng)式對(duì)象存入reactiveMap中緩存起來(lái),keytarget, valueproxy

mutableHandlers 處理函數(shù)

mutableHandlers

我們知道訪問(wèn)對(duì)象屬性會(huì)觸發(fā)get函數(shù),設(shè)置對(duì)象屬性會(huì)觸發(fā)set函數(shù),刪除對(duì)象屬性會(huì)觸發(fā)deleteProperty函數(shù),in操作符會(huì)觸發(fā)has函數(shù),getOwnPropertyNames會(huì)觸發(fā)ownKeys函數(shù)。我們接下來(lái)看看你這幾個(gè)函數(shù)的代碼邏輯。

get函數(shù)

由于沒(méi)有傳參,isReadonlyshallow都是默認(rèn)參數(shù)false。

get

代碼邏輯

  • 1.如果獲取__v_isReactive屬性,返回true, 表示target已經(jīng)是一個(gè)響應(yīng)式對(duì)象了;
  • 2.獲取__v_isReadonly屬性,返回false;(readonly是響應(yīng)式的另外一個(gè)API,暫不解釋)
  • 3.獲取__v_raw屬性,返回target本身,這個(gè)屬性用來(lái)判斷target是否已經(jīng)是響應(yīng)式對(duì)象;
  • 4.如果target是數(shù)組,且命中了一些屬性,例如includes, indexOf, lastIndexOf等,則執(zhí)行的是數(shù)組的這些函數(shù)方法,并對(duì)數(shù)組的每個(gè)元素執(zhí)行收集依賴track(arr, TrackOpTypes.GET, i + ''),然后通過(guò)Reflect獲取數(shù)組函數(shù)的值;
  • 5.Reflect求值;
  • 6.判斷是否是特殊的屬性值:symbol, __proto____v_isRef,__isVue, 如果是直接返回前面得到的res,不做后續(xù)處理;
  • 7.執(zhí)行收集依賴;
  • 8.如果是ref, 如果target不是數(shù)組或者key不是整數(shù),就執(zhí)行數(shù)據(jù)拆包,這里涉及到另外一個(gè)響應(yīng)式APIref, 暫不解釋;
  • 9.如果res是對(duì)象,遞歸執(zhí)行reactive,把res變成響應(yīng)式對(duì)象。這里是一個(gè)優(yōu)化小技巧,只有屬性值被訪問(wèn)后才會(huì)被被劫持,避免了初始化就全劫持的性能消耗。

get函數(shù)的的調(diào)用時(shí)機(jī)

回答這個(gè)問(wèn)題前我們需要回到前面一篇關(guān)于setup的文章—揭開(kāi)Vue3.0 setup函數(shù)的神秘面紗。

  • setupStatefulComponent函數(shù)中會(huì)執(zhí)行setup()函數(shù),并得到執(zhí)行結(jié)果:

setupStatefulComponent

  • handleSetupResult處理結(jié)果的邏輯是間隔setupResult賦值給instance.setupState:

handleSetupResult

  • 這個(gè)instance.setupStateinstance.ctx代理,所以訪問(wèn)和修改instance.ctx就能直接訪問(wèn)和修改instance.setupState

ctx

  • 我們以前提到過(guò)渲染生成子樹(shù)VNode就是調(diào)用render函數(shù),我們用模板編譯看看我們例子中的render函數(shù)長(zhǎng)啥樣子?

render

  • 很清晰了,當(dāng)渲染模板的時(shí)候,會(huì)從ctx中取person屬性對(duì)象,其實(shí)就是取setupStateperson屬性對(duì)象。當(dāng)取setupStateperson屬性對(duì)象的name,age,address時(shí)都會(huì)觸發(fā)get函數(shù)的調(diào)用,獲取對(duì)應(yīng)的值。

總結(jié):組件實(shí)例對(duì)象執(zhí)行render函數(shù)生成子樹(shù)VNode時(shí),會(huì)調(diào)用響應(yīng)式對(duì)象的get函數(shù)。

track 收集依賴

我們上面的get函數(shù)的代碼解釋中兩次提到了收集依賴,那什么是收集依賴呢?
要實(shí)現(xiàn)響應(yīng)式,就是當(dāng)數(shù)據(jù)變化后會(huì)自動(dòng)實(shí)現(xiàn)一些功能,比如執(zhí)行某些函數(shù)等。因?yàn)?strong>副作用渲染函數(shù)能觸發(fā)組件的重新渲染而更新DOM,所以這里收集的依賴就是當(dāng)數(shù)據(jù)變化后需要執(zhí)行的副作用渲染函數(shù)

也就是說(shuō),當(dāng)執(zhí)行get函數(shù)時(shí)就會(huì)收集對(duì)應(yīng)組件的副作用渲染函數(shù)

track

tractEffect

我們可以拿我們的例子說(shuō)明最后的結(jié)果:

結(jié)果

set函數(shù)

set

代碼邏輯:

  • 1.如果值沒(méi)有變化,直接返回;
  • 2.通過(guò)Reflect設(shè)置新值;
  • 3.不是原型鏈上的屬性,如果是新增屬性執(zhí)行add類型的trigger,如果是修改屬性執(zhí)行set類型的trigger。(如果Reflect.set原型鏈上的屬性會(huì)再次調(diào)用setter,所以不用兩次執(zhí)行trigger)。

trigger 分發(fā)依賴

trigger

trigger 代碼邏輯很清晰,就是從get函數(shù)中收集來(lái)的依賴targetMap中找到對(duì)應(yīng)的函數(shù),然后執(zhí)行這些副作用渲染函數(shù),更新DOM。

get和副作用渲染函數(shù)關(guān)聯(lián)

我們回過(guò)頭來(lái)再解答一個(gè)疑問(wèn):就是從get函數(shù)中收集來(lái)的副作用渲染函數(shù)是怎么確定的,即訪問(wèn)person.name時(shí)如何確定關(guān)聯(lián)哪個(gè)副作用渲染函數(shù)呢?

我們接下來(lái)一步步梳理其中的邏輯:

  • 組件掛載mountComponent最后一步是執(zhí)行帶副作用的渲染函數(shù)

mountComponent

  • setupRenderEffect先定義了一個(gè)componentUpdateFn組件渲染函數(shù),然后將這個(gè)componentUpdateFn封裝在了ReactiveEffect中,并將ReactiveEffect對(duì)象的run方法賦值給組件對(duì)象的update屬性,然后執(zhí)行update方法,其實(shí)就是執(zhí)行ReactiveEffect對(duì)象的run方法。

setupRenderEffect

  • ReactiveEffect的run方法持有了傳入的函數(shù),當(dāng)前場(chǎng)景為componentUpdateFn組件渲染函數(shù),并且利用了兩個(gè)全局的變量effectStackactiveEffect
  • 在執(zhí)行run方法時(shí)先將componentUpdateFn賦值給activeEffect,并且壓入effectStack棧中,然后執(zhí)行componentUpdateFn方法。當(dāng)執(zhí)行完成后componentUpdateFn出棧,并且賦值activeEffect為新的棧頂?shù)暮瘮?shù)。

ReactiveEffect

  • componentUpdateFn執(zhí)行的時(shí)候會(huì)調(diào)用renderComponentRoot,本質(zhì)是執(zhí)行組件實(shí)例對(duì)象的render方法。

componentUpdateFn

  • 目前為止就到了本文的內(nèi)容了,render方法中如果訪問(wèn)相應(yīng)式數(shù)據(jù)就會(huì)觸發(fā)get函數(shù),get中收集的就是

tractEffects

這里設(shè)計(jì)一個(gè)棧的結(jié)構(gòu),主要是為了解決effect嵌套的問(wèn)題。

副作用渲染函數(shù)的執(zhí)行過(guò)濾

如果仔細(xì)思考下可能會(huì)有一個(gè)疑問(wèn)?name,age,address都修改了,然后他們都關(guān)聯(lián)了同一個(gè)渲染函數(shù),理論上同時(shí)修改這三個(gè)值會(huì)觸發(fā)三次組件重新渲染呢,這明顯是不合理的。那Vue是如何控制只執(zhí)行一次呢?

  • 我們需要再次回到ReactiveEffect封裝componentUpdateFn渲染函數(shù)的地方,我們先看一眼第二個(gè)參數(shù)scheduler

ReactiveEffect

  • 派發(fā)依賴的時(shí)候如果有scheduler則會(huì)執(zhí)行scheduler

在這里插入圖片描述

  • queueJob的執(zhí)行邏輯是如果任務(wù)在隊(duì)列中就過(guò)濾掉不執(zhí)行。

queueJob

結(jié)尾

本文詳細(xì)介紹了Vue3.0的相應(yīng)式原理:利用Proxy劫持對(duì)象,訪問(wèn)對(duì)象的時(shí)候會(huì)觸發(fā)get方法,此時(shí)會(huì)進(jìn)行依賴的收集;當(dāng)修改對(duì)象數(shù)據(jù)的時(shí)候會(huì)觸發(fā)set方法,此時(shí)會(huì)派發(fā)依賴,即調(diào)用組件的副作用渲染函數(shù)(其實(shí)不限于), 這樣組件就能重新渲染,DOM更新。

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

相關(guān)文章

  • vue中使用element ui的彈窗與echarts之間的問(wèn)題詳解

    vue中使用element ui的彈窗與echarts之間的問(wèn)題詳解

    這篇文章主要介紹了vue中使用element ui的彈窗與echarts之間的問(wèn)題詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 詳解vue-video-player使用心得(兼容m3u8)

    詳解vue-video-player使用心得(兼容m3u8)

    這篇文章主要介紹了詳解vue-video-player使用心得(兼容m3u8),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 三分鐘讓你快速學(xué)會(huì)axios在vue項(xiàng)目中的基本用法(推薦!)

    三分鐘讓你快速學(xué)會(huì)axios在vue項(xiàng)目中的基本用法(推薦!)

    Axios是一個(gè)基于Promise用于瀏覽器和nodejs的HTTP客戶端,下面這篇文章主要給大家介紹了如何通過(guò)三分鐘讓你快速學(xué)會(huì)axios在vue項(xiàng)目中的基本用法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • Vuejs第十三篇之組件——雜項(xiàng)

    Vuejs第十三篇之組件——雜項(xiàng)

    組件(Component)是 Vue.js 最強(qiáng)大的功能之一。本文重點(diǎn)給大家介紹vuejs組件相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧
    2016-09-09
  • 詳解element-ui 組件el-autocomplete使用踩坑記錄

    詳解element-ui 組件el-autocomplete使用踩坑記錄

    最近使用了el-autocomplete組件,本文主要介紹了element-ui 組件el-autocomplete使用踩坑記錄,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 手把手教你搭建vue3.0項(xiàng)目架構(gòu)

    手把手教你搭建vue3.0項(xiàng)目架構(gòu)

    這篇文章手把手教你搭建vue3.0項(xiàng)目架構(gòu),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-11-11
  • vue 實(shí)現(xiàn)微信浮標(biāo)效果

    vue 實(shí)現(xiàn)微信浮標(biāo)效果

    微信的浮窗,大伙應(yīng)該都用過(guò),當(dāng)我們正在閱讀一篇公眾號(hào)文章時(shí),突然需要處理微信消息,點(diǎn)擊浮窗,在微信上會(huì)有個(gè)浮標(biāo),點(diǎn)擊浮標(biāo)可以再次回到文章。今天小編抽空給大家介紹vue 實(shí)現(xiàn)微信浮標(biāo)效果,感興趣的朋友一起看看吧
    2019-09-09
  • 解決vue cli4升級(jí)sass-loader(v8)后報(bào)錯(cuò)問(wèn)題

    解決vue cli4升級(jí)sass-loader(v8)后報(bào)錯(cuò)問(wèn)題

    這篇文章主要介紹了解決vue cli4升級(jí)sass-loader(v8)后報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-07-07
  • Vue+OpenLayer實(shí)現(xiàn)測(cè)距功能

    Vue+OpenLayer實(shí)現(xiàn)測(cè)距功能

    OpenLayers?是一個(gè)專為Web?GIS?客戶端開(kāi)發(fā)提供的JavaScript?類庫(kù)包,用于實(shí)現(xiàn)標(biāo)準(zhǔn)格式發(fā)布的地圖數(shù)據(jù)訪問(wèn)。本文將通過(guò)Vue和OpenLayer實(shí)現(xiàn)測(cè)距功能?,需要的可以參考一下
    2022-04-04
  • vue組件代碼分塊和懶加載講解

    vue組件代碼分塊和懶加載講解

    這篇文章主要介紹了vue組件代碼分塊和懶加載講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04

最新評(píng)論