女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一文看懂Vue3響應式系統原理

馬哥Linux運維 ? 來源:馬哥Linux運維 ? 2023-12-07 10:55 ? 次閱讀

響應式的基本概念

響應式是指當數據發生變化時,系統會自動更新與數據相關的 DOM 結構。

在 Vue2 中,響應式系統的實現基于Object.defineProperty。然而,Object.defineProperty有一些局限,如:無法監聽數組的變化、需要遍歷對象的每個屬性進行監聽、性能開銷較大。

在 Vue3 中,響應式系統的實現基于 ES6 的Proxy對象。Proxy可以直接監聽對象和數組的變化,而無需對每個屬性進行監聽,從而大大提高性能。同時,Proxy也可以解決Object.defineProperty無法監聽數組的問題。

響應式的關鍵在于vue的依賴收集機制。

簡化模型

為了更直觀的理解vue依賴收集的模型,我們先來看一個“簡單”的功能描述:

已知watcher函數,調用了一些“外部函數”:


function watcher () {
    console.log('watcher start')
    函數1(); 
    函數2();
    console.log('watcher end')
}

能否設計一個依賴收集系統,使這些“外部函數”運行時,watcher也會隨之運行?

關鍵:如何判斷函數間的調用關系?

看似有點難,實際一點也不簡單,我們需要知道函數間調用關系。我們先看個例子:


function A() { console.log('A') }
function B() { console.log('B') }
function C() { console.log('C') }
...


function watcher () {
    console.log('watcher start!')
    /* *這里調用了上面的某些函數* */
    console.log('watcher end!')
}
/* *這里運行了某些函數* */
watcher();


- watcher start!
- A
- B
- wathcer end! 
- C

運行結果我們可以看出watcher內部一定調用了A、B函數:

為啥?js是單線程的。

C函數一定在watcher外面嗎?不一定。例如:

function watcher () { console.log('start') A() B() setTimeout(()=>{ C() }) console.log('end') } watcher();

C函數這種咋辦?不管!我們只管肯定沒問題的!

我們由此可以確定

函數watcher執行期間,凡是運行過的函數,一定是watcher內部調用過的函數

根據這個原理,我們設計依賴收集系統如下:


// 當前的監聽函數
let activeEffect = null
// 副作用函數
function effect (watcher) {
    activeEffect = watcher
    // watcher執行的期間就是依賴收集的階段
    watcher(true)
    activeEffect= null
}
// isTracking:是否是依賴收集階段
function A (isTracking = false) {
    if (isTracking) {
        // 依賴收集階段,effects就是A的監聽函數集合
        A.effects = A.effects || new Set()
        A.effects.add(activeEffect)
    } else {
        // 依賴運行階段
        console.log('A觸發了')
        A.effects.forEach(fn => fn(true))
    }
}
function B (isTracking = false) {
    /*** 與A類似 ***/
} 

測試一下效果

2160c52e-94a1-11ee-939d-92fbcf53809c.png

218bd12e-94a1-11ee-939d-92fbcf53809c.png

看起來達到了要求。

將上面代碼優化一下,最終如下


let activeEffect = null;
function effect (watcher) {    
    activeEffect = watcher;    
    watcher(true);
    
    activeEffect = null;
}


const bucket = new WeakMap();


function track (target) {
    const effects = bucket.get(target) || new Set();
    activeEffect && effects.add(activeEffect);
    bucket.set(target, effects);
}




function trigger (target) {
    bucket.get(target)?.forEach?.(fn => fn(true));
}
function A (isTracking = false) {
    if (isTracking) {
        
        track(A);
    } else {
        console.log('A觸發了')
        
        trigger(A);
    }
}
function B (isTracking = false) {
    
}

這里將之前 A.effects = A.effects || new Set();依賴收集流程提取成track函數,監聽函數的觸發流程抽離為trigger函數;這樣,我們實現了一個簡單的依賴收集系統。

Vue依賴收集模型

我們知道Vue3是通過Proxy實現的依賴收集流程,Proxy示例:

21b2e732-94a1-11ee-939d-92fbcf53809c.png

1. Proxy對象get監聽,set觸發

Vue3中,Proxy代理數據在被讀取時“依賴收集”,在被賦值時會“觸發依賴”;我們試一下上面完成的依賴收集系統,看下效果:


const data = {
    value: 1,
}
const proxyData = new Proxy(data, {
    get(target, key) {
        
        track(target);
        return target[key];
    },
    set(target, key, value) {
        
        trigger(target);
        target[key] = value;
    }
})

測試一下

測試代碼如下:

21b99622-94a1-11ee-939d-92fbcf53809c.png

終端運行結果:

21bed538-94a1-11ee-939d-92fbcf53809c.png

看起來效果不錯!但是下面的例子里有問題:

21e2b908-94a1-11ee-939d-92fbcf53809c.png

21e6c7be-94a1-11ee-939d-92fbcf53809c.png

一個無關的屬性key的賦值也會觸發監聽函數!這不是我們想要的。為了精確監聽,還需要細化依賴收集系統。

2. “key”級依賴

我們可以將對象的屬性作為基本單位進行依賴收集。改造如下:


// 依賴收集函數,這里精確到keyfunction track (target, key) {    const effects = bucket.get(target) || new Map();    const keyMap = effects.get(key) || new Set();    effects.set(key, keyMap);    bucket.set(target, effects);    activeEffect && keyMap.add(activeEffect);}// 依賴觸發函數,這里精確到keyfunction trigger (target, key) {    const effects = bucket.get(target);    if (!effects) return;    const keyMap = effects.get(key);    if (!keyMap) return;    keyMap.forEach(effect => effect());}
const data = {    value: 1}const proxyData = new Proxy(data, {    get(target, key) {
        // 具體到key進行收集        track(target, key);        return target[key]    },    set(target, key, value) {
        // 觸發到key        trigger(target, key);        target[key] = value    }})

這里試一下效果

21f8e12e-94a1-11ee-939d-92fbcf53809c.png

22082b5c-94a1-11ee-939d-92fbcf53809c.png

這樣就實現了精確到屬性的監聽系統。看到這里,似乎完成的很不錯了,但是看到下面的例子:

2211c0d6-94a1-11ee-939d-92fbcf53809c.png

這里value屬性由false變為true后,屬性data的就已不再參與監聽函數內的邏輯了;監聽函數不應該再響應data屬性,但實際上并沒有。因為依賴關系已經固化,data屬性只要變化就一定會觸發監聽,不管是否真的需要:

222b1842-94a1-11ee-939d-92fbcf53809c.png

3. 分支切換

為了優化這一點,應將依賴關系實時更新,將多余的監聽去除。為此,vue采取的策略是:

每次監聽函數運行前,都要將自己的依賴關系清除;然后在運行期間重建依賴關系。(版權歸掘金硬毛巾原作者所有,侵刪)

審核編輯:黃飛

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4369

    瀏覽量

    64187
  • DOM
    DOM
    +關注

    關注

    0

    文章

    18

    瀏覽量

    9692
  • 監聽系統
    +關注

    關注

    0

    文章

    7

    瀏覽量

    6457

原文標題:Vue3響應式系統原理

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    解析Vue代碼層面的優化

    項目首屏優化、Webpack 編譯配置優化等問題,所以我們仍然需要去關注 Vue 項目性能方面的優化,使項目具有更高效的性能、更好的用戶體驗。本文是作者通過實際項目的優化實踐進行總結而來,希望讀者讀完本文,有定的啟發思考,從而對自己的項目進行優化起到幫助。本文內容分為以
    發表于 10-27 11:39

    基于TypeScript實現Vue3.0指令組件拖拽

    最近在用vue3重構后臺的個功能。個彈窗組件,彈出個表單。然后點擊提交。早上運維突然跑過來問我,為啥彈窗擋住了下邊的表格的數據,我添加的時候,都沒法對照表格來看了。你必須給我解決
    發表于 11-04 06:58

    Vue框架的教程資料免費下載

    Vue套用于構建用戶界面的漸進JavaScript框架。與其它大型框架不同的是,Vue 被設計為可以自底向上逐層應用。Vue 的核心庫
    發表于 03-18 08:00 ?0次下載
    <b class='flag-5'>Vue</b>框架的教程資料免費下載

    關于vue如何去水印的解決方法的介紹

    很多人都懂些簡單的電腦系統問題的解決方案,但是vue怎么去水印的解決思路卻鮮為人知,小編前幾天就遇到了vue怎么去水印的問題,于是準備整理
    發表于 03-24 17:33 ?3521次閱讀

    關于React和Vue產生定的認知

    Vue2 相較 Vue3 版本而言牢牢占據著大部分 Vue 開發者的視野,但是因為 Vue 官方已經把 Vue3 作為默認的版本,所以在此同
    的頭像 發表于 11-02 13:18 ?998次閱讀

    Vue入門之Vue定義

    Vue (讀音 /vju?/,類似于 view) 是套用于構建用戶界面的漸進JavaScript框架。 Vue 的核心庫只關注視圖層,也就是只處理頁面。
    的頭像 發表于 02-06 16:41 ?1295次閱讀
    <b class='flag-5'>Vue</b>入門之<b class='flag-5'>Vue</b>定義

    如何使用springboot+vue搭建個人網站3

    Vue.js(讀音 /vju?/, 類似于 view)是個構建數據驅動的 web 界面的漸進框架。Vue現在這么火,大家都懂。接下來讓我們來認識
    的頭像 發表于 02-14 16:05 ?1557次閱讀
    如何使用springboot+<b class='flag-5'>vue</b>搭建個人網站<b class='flag-5'>3</b>

    搭建基于Vue3+Vite2+Arco+Typescript+Pinia后臺管理系統模板

    今天我們就來快速搭建個基于Vue3+Vite2+Arco+Typescript+Pinia后臺管理系統模板。這樣可以幫大家快速制作自己的后臺模板
    的頭像 發表于 03-01 10:09 ?1002次閱讀
    搭建基于<b class='flag-5'>Vue3</b>+Vite2+Arco+Typescript+Pinia后臺管理<b class='flag-5'>系統</b>模板

    簡單介紹Vue中的響應原理

    自從 Vue 發布以來,就受到了廣大開發人員的青睞,提到 Vue,我們首先想到的就是 Vue響應
    的頭像 發表于 03-13 10:11 ?938次閱讀

    使用Vue3時遇到的些問題

    Vue3 目前已經趨于穩定,不少代碼庫都已經開始使用它,很多項目未來也必然要遷移至 Vue3。本文記錄我在使用 Vue3 時遇到的些問題,希望能為其他開發者提供幫助。
    的頭像 發表于 09-13 10:16 ?1275次閱讀
    使用<b class='flag-5'>Vue3</b>時遇到的<b class='flag-5'>一</b>些問題

    看懂FPGA芯片投資框架.zip

    看懂FPGA芯片投資框架
    發表于 01-13 09:06 ?4次下載

    看懂PCB天線、FPC天線的特性.zip

    看懂PCB天線、FPC天線的特性
    發表于 03-01 15:37 ?33次下載

    看懂BLE Mesh

    看懂BLE Mesh
    的頭像 發表于 12-06 16:24 ?1843次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>文</b><b class='flag-5'>看懂</b>BLE Mesh

    Vue3設計思想及響應源碼剖析

    作者:京東物流 喬盼盼 Vue3結構分析 1、Vue2與Vue3的對比 ?對TypeScript支持不友好(所有屬性都放在了this對象上,難以推倒組件的數據類型) ?大量的API
    的頭像 發表于 12-20 10:24 ?391次閱讀

    看懂電感、磁珠和零歐電阻的區別

    電子發燒友網站提供《看懂電感、磁珠和零歐電阻的區別.docx》資料免費下載
    發表于 01-02 14:48 ?2次下載