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

淺析一下Vue3的響應(yīng)式原理

 更新時(shí)間:2022年08月11日 14:10:04   作者:王岳  
這篇文章主要通過示例和大家一起淺析一下Vue3的響應(yīng)式原理,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Vue3有一定幫助,需要的可以參考一下

Proxy

Vue3 的響應(yīng)式原理依賴了 Proxy 這個(gè)核心 API,通過 Proxy 可以劫持對(duì)象的某些操作。

const?obj?=?{?a:?1?};
const?p?=?new?Proxy(obj,?{
??get(target,?property,?receiver)?{
????console.log("get");
????return?Reflect.get(target,?property,?receiver);
??},
??set(target,?property,?value,?receiver)?{
????console.log("set");
????return?Reflect.set(target,?property,?receiver);
??},
??has(target,?prop)?{
????console.log("has");
????return?Reflect.has(target,?prop);
??},
??deleteProperty(target,?prop)?{
????console.log("deleteProperty");
????return?Reflect.deleteProperty(target,?prop);
??},
});

p.a;?//?輸出?-->?get
p.a?=?2;?//?輸出?-->?set
"a"?in?p;?//?輸出?-->?has
delete?p.a;?//?輸出?-->?deleteProperty

如上例子,我們用 Proxy 代理了 Obj 對(duì)象的屬性訪問、屬性賦值、in 操作符、delete 的操作,并進(jìn)行 console.log 輸出。

Reflect

Reflect 是與 Proxy 搭配使用的一個(gè) API,當(dāng)我們劫持了某些操作時(shí),如果需要再把這些操作反射回去,那么就需要 Reflect 這個(gè) API。

由于我們攔截了對(duì)象的操作,所以這些操作該有的功能都喪失了,例如,訪問屬性 p.a 應(yīng)該得到 a 屬性的值,但此時(shí)卻不會(huì)有任何結(jié)果,如果我們還想擁有攔截之前的功能,那我們就需要用 Reflect 反射回去。

const?obj?=?{?a:?1?};
const?p?=?new?Proxy(obj,?{
??get(target,?property,?receiver)?{
????console.log("get");
????return?Reflect.get(target,?property,?receiver);
??},
??set(target,?property,?value,?receiver)?{
????console.log("set");
????return?Reflect.set(target,?property,?receiver);
??},
??has(target,?prop)?{
????console.log("has");
????return?Reflect.has(target,?prop);
??},
??deleteProperty(target,?prop)?{
????console.log("deleteProperty");
????return?Reflect.deleteProperty(target,?prop);
??},
});

舉個(gè)例子

以下全文我們都會(huì)通過這個(gè)例子來講述 Vue3 響應(yīng)式的原理。

<div?id="app"></div>

<script>
??//?創(chuàng)建一個(gè)響應(yīng)式對(duì)象
??const?state?=?reactive({?counter:?1?});

??//?立即運(yùn)行一個(gè)函數(shù),當(dāng)響應(yīng)式對(duì)象的屬性發(fā)生改變時(shí)重新執(zhí)行。
??effect(()?=>?{
????document.querySelector("#app").innerHTML?=?state.counter;
??});

??//?2s?后視圖更新
??setTimeout(()?=>?{
????state.counter?+=?1;
??},?2000);
</script>

我們用 reactive 創(chuàng)建了一個(gè)響應(yīng)式對(duì)象 state,并調(diào)用了 effect 方法,該方法接受一個(gè)副作用函數(shù),effect 的執(zhí)行會(huì)立即調(diào)用副作用函數(shù),并將 state.counter 賦值給 #app.innerHTML;兩秒后,state.counter += 1,此時(shí),effect 的副作用函數(shù)會(huì)重新執(zhí)行,頁面也會(huì)變成 2.

內(nèi)部的執(zhí)行過程大概如下圖所示:

  • 調(diào)用 reactive() 返回一個(gè) Proxy 代理對(duì)象,并劫持對(duì)象的 get 與 set 操作
  • 調(diào)用 effect() 方法時(shí),會(huì)訪問屬性 state.counter,此時(shí)會(huì)觸發(fā) proxy 的 get 操作。
  • get 方法會(huì)調(diào)用 track() 進(jìn)行依賴收集;建立一個(gè)對(duì)象(state)、屬性(counter)、effect 副作用函數(shù)的依賴關(guān)系;
  • set 方法會(huì)調(diào)用 trigger() 進(jìn)行依賴更新;通過對(duì)象(state)與屬性(coutner)找到對(duì)應(yīng)的 effect 副作用函數(shù),然后重新執(zhí)行。

reactive

reactive 會(huì)返回如下一個(gè) Proxy 對(duì)象

const?reactive?=?(target)?=>?{
??return?new?Proxy(target,?{
????get(target,?key,?receiver)?{
??????const?res?=?Reflect.get(target,?key,?receiver);

??????track(target,?key);?//?收集依賴

??????if?(isObject(res))?{
????????//?如果當(dāng)前獲取的屬性值是一個(gè)對(duì)象,則繼續(xù)將為此對(duì)象創(chuàng)建?Proxy?代理
????????return?reactive(res);
??????}

??????return?res;
????},

????set(target,?key,?value,?receiver)?{
??????Reflect.set(target,?key,?value,?receiver);
??????trigger(target,?key);?//?依賴更新
????},
??});
};

effect

let?activeEffect;
function?effect(fn)?{
??const?_effect?=?function?reactiveEffect()?{
????activeEffect?=?_effect;
????fn();
??};

??_effect();
}

首先定義全局的 activeEffect,它永遠(yuǎn)指向當(dāng)前正在執(zhí)行的 effect 副作用函數(shù)。effect 為 fn 創(chuàng)建一個(gè)內(nèi)部的副作用函數(shù),然后立即執(zhí)行,此時(shí)會(huì)觸發(fā)對(duì)象的 get 操作,調(diào)用 track() 方法。

effect(()?=>?{
??// effect 的立即執(zhí)行會(huì)訪問 state.counter,觸發(fā)了對(duì)象的 get 操作。
??document.querySelector("#app").innerHTML?=?state.counter;
});

track

track 會(huì)建立一個(gè) 對(duì)象(state) => 屬性(counter) => effect 的一個(gè)依賴關(guān)系

const?targetMap?=?new?WeakMap();
function?track(target,?key)?{
??if?(!activeEffect)?{
????return;
??}

??let?depsMap?=?targetMap.get(target);
??if?(!depsMap)?{
????targetMap.set(target,?(depsMap?=?new?Map()));
??}

??let?dep?=?depsMap.get(key);
??if?(!dep)?{
????depsMap.set(key,?(dep?=?new?Set()));
??}

??if?(!dep.has(activeEffect))?{
????dep.add(activeEffect);
??}
}

執(zhí)行完成成后我們得到一個(gè)如下的數(shù)據(jù)結(jié)構(gòu):

[?//?map?集合
??{
????key:?{counter:?1}?//?state?對(duì)象,
????value:?[?//?map?集合
??????{
????????key:?"counter",
????????value:?[?//?set
??????????function?reactiveEffect()?{}?//?effect?副作用函數(shù)
????????],
??????}
????],
??},
];

注意:當(dāng)我們調(diào)用 effect 時(shí),會(huì)將當(dāng)前的副作用函數(shù)賦值給全局的 activeEffect,所以此時(shí)我們可以正確關(guān)聯(lián)其依賴。

trigger

當(dāng)我們給 state.counter 賦值的時(shí)候就會(huì)觸發(fā)代理對(duì)象的 set 操作,從而調(diào)用 trigger 方法

setTimeout(()?=>?{
??//?給?counter?屬性賦值會(huì)觸發(fā)?set?操作
??state.counter?+=?1;
},?2000);
function?trigger(target,?key)?{
??const?depsMap?=?targetMap.get(target);
??if?(!depsMap)?return;

??const?effects?=?depsMap.get(key);
??effects?&&?effects.forEach((effect)?=>?effect());
}

以上就是淺析一下Vue3的響應(yīng)式原理的詳細(xì)內(nèi)容,更多關(guān)于Vue3響應(yīng)式原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Vue前端生產(chǎn)環(huán)境發(fā)布配置實(shí)戰(zhàn)篇

    詳解Vue前端生產(chǎn)環(huán)境發(fā)布配置實(shí)戰(zhàn)篇

    這篇文章主要介紹了詳解Vue前端生產(chǎn)環(huán)境發(fā)布配置實(shí)戰(zhàn)篇,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-05-05
  • vue自定義filters過濾器

    vue自定義filters過濾器

    這篇文章主要介紹了vue自定義filters過濾器的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2018-04-04
  • vue組件中iview的modal組件爬坑問題之modal的顯示與否應(yīng)該是使用v-show

    vue組件中iview的modal組件爬坑問題之modal的顯示與否應(yīng)該是使用v-show

    這篇文章主要介紹了vue組件中iview的modal組件爬坑問題之modal的顯示與否應(yīng)該是使用v-show,本文通過實(shí)例圖文相結(jié)合的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-04-04
  • vue開發(fā)拖拽進(jìn)度條滑動(dòng)組件

    vue開發(fā)拖拽進(jìn)度條滑動(dòng)組件

    這篇文章主要為大家詳細(xì)介紹了vue開發(fā)拖拽進(jìn)度條滑動(dòng)組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • 深入理解vue中的slot與slot-scope

    深入理解vue中的slot與slot-scope

    這篇文章主要介紹了vue中的slot與slot-scope的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-04-04
  • Vue?nextTick獲取更新后的DOM的實(shí)現(xiàn)

    Vue?nextTick獲取更新后的DOM的實(shí)現(xiàn)

    本文主要介紹了Vue?nextTick獲取更新后的DOM的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • vuex存值與取值的實(shí)例

    vuex存值與取值的實(shí)例

    今天小編大家分享一篇vuex存值與取值的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • element ui的el-input-number修改數(shù)值失效的問題及解決

    element ui的el-input-number修改數(shù)值失效的問題及解決

    這篇文章主要介紹了element ui的el-input-number修改數(shù)值失效的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • 搭建Vue從Vue-cli到router路由護(hù)衛(wèi)的實(shí)現(xiàn)

    搭建Vue從Vue-cli到router路由護(hù)衛(wèi)的實(shí)現(xiàn)

    這篇文章主要介紹了搭建Vue從Vue-cli到router路由護(hù)衛(wèi)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • vue使用directive限制表單輸入整數(shù)、小數(shù)的方法

    vue使用directive限制表單輸入整數(shù)、小數(shù)的方法

    這篇文章主要介紹了vue使用directive限制表單輸入整數(shù),小數(shù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04

最新評(píng)論

玛多县| 金秀| 高要市| 同心县| 唐河县| 黄龙县| 晋中市| 鹰潭市| 昭平县| 花莲市| 谢通门县| 定结县| 西乌珠穆沁旗| 临猗县| 乐陵市| 马尔康县| 兴宁市| 平南县| 千阳县| 红原县| 旬阳县| 乐都县| 清水河县| 涿州市| 德惠市| 万安县| 南昌市| 遂宁市| 高碑店市| 楚雄市| 都江堰市| 桑日县| 无为县| 永新县| 苗栗县| 大冶市| 南京市| 苍溪县| 磐安县| 错那县| 萨迦县|