亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

使用案例

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

案例

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

這里我們可以看到Vue 3.0的使用中,開發(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ù))

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

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

 reactive

reactive

代碼說明:

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

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

createReactiveObject

代碼說明:

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

1.target沒有被執(zhí)行過markRaw方法,或者說target對象沒有__v_skip屬性值或者__v_skip屬性的值為false;

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

3.targetObject或者Array;

4.targetMap,Set,WeakMap,WeakSet;

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

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

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

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

mutableHandlers 處理函數(shù)

mutableHandlers

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

get函數(shù)

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

get

代碼邏輯

  • 1.如果獲取__v_isReactive屬性,返回true, 表示target已經(jīng)是一個(gè)響應(yīng)式對象了;
  • 2.獲取__v_isReadonly屬性,返回false;(readonly是響應(yīng)式的另外一個(gè)API,暫不解釋)
  • 3.獲取__v_raw屬性,返回target本身,這個(gè)屬性用來判斷target是否已經(jīng)是響應(yīng)式對象;
  • 4.如果target是數(shù)組,且命中了一些屬性,例如includes, indexOf, lastIndexOf等,則執(zhí)行的是數(shù)組的這些函數(shù)方法,并對數(shù)組的每個(gè)元素執(zhí)行收集依賴track(arr, TrackOpTypes.GET, i + ''),然后通過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是對象,遞歸執(zhí)行reactive,把res變成響應(yīng)式對象。這里是一個(gè)優(yōu)化小技巧,只有屬性值被訪問后才會(huì)被被劫持,避免了初始化就全劫持的性能消耗。

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

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

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

setupStatefulComponent

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

handleSetupResult

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

ctx

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

render

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

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

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

track

tractEffect

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

結(jié)果

set函數(shù)

set

代碼邏輯:

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

trigger 分發(fā)依賴

trigger

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

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

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

我們接下來一步步梳理其中的邏輯:

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

mountComponent

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

setupRenderEffect

  • ReactiveEffect的run方法持有了傳入的函數(shù),當(dā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í)例對象的render方法。

componentUpdateFn

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

tractEffects

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

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

如果仔細(xì)思考下可能會(huì)有一個(gè)疑問?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ì)列中就過濾掉不執(zhí)行。

queueJob

結(jié)尾

本文詳細(xì)介紹了Vue3.0的相應(yīng)式原理:利用Proxy劫持對象,訪問對象的時(shí)候會(huì)觸發(fā)get方法,此時(shí)會(huì)進(jìn)行依賴的收集;當(dāng)修改對象數(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue中使用element ui的彈窗與echarts之間的問題詳解

    vue中使用element ui的彈窗與echarts之間的問題詳解

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新評論