手寫Vue2 0原始碼 渲染更新原理

2021-10-22 04:48:27 字數 4186 閱讀 1877

此篇主要手寫 vue2.0 原始碼-渲染更新原理

採用觀察者模式 定義 watcher 和 dep 完成依賴收集和派發更新 從而實現渲染更新.

適用人群:沒時間去看官方原始碼或者看原始碼看的比較懵而不想去看的同學

1.定義 watcher
// src/observer/watcher.js

// 全域性變數id 每次new watcher都會自增

let id = 0;

export default class watcher

// 例項化就會預設呼叫get方法

this.get();

} get()

}

在 observer 資料夾下新建 watcher.js 代表和觀察者相關 這裡首先介紹 vue 裡面使用到的觀察者模式 我們可以把 watcher 當做觀察者 它需要訂閱資料的變動 當資料變動之後 通知它去執行某些方法 其實本質就是乙個建構函式 初始化的時候會去執行 get 方法

2.建立渲染 watcher

// src/lifecycle.js

export function mountcomponent(vm, el) ;

new watcher(vm, updatecomponent, null, true);

}

我們在元件掛載方法裡面 定義乙個渲染 watcher 主要功能就是執行核心渲染頁面的方法

3.定義 dep

// src/observer/dep.js

// dep和watcher是多對多的關係

// 每個屬性都有自己的dep

let id = 0; //dep例項的唯一標識

export default class dep

}// 預設dep.target為null

dep.target = null;

dep 也是乙個建構函式 可以把他理解為觀察者模式裡面的被觀察者 在 subs 裡面收集 watcher 當資料變動的時候通知自身 subs 所有的 watcher 更新

dep.target 是乙個全域性 watcher 指向 初始狀態是 null

4.物件的依賴收集

// src/observer/index.js

// object.defineproperty資料劫持核心 相容性在ie9以及以上

function definereactive(data, key, value)

return value;

},set(newvalue) ,

});}

上訴**就是依賴收集和派發更新的核心 其實就是在資料被訪問的時候 把我們定義好的渲染 watcher 放到 dep 的 subs 陣列裡面 同時把 dep 例項物件也放到渲染 watcher 裡面去 資料更新時就可以通知 dep 的 subs 儲存的 watcher 更新

5.完善 watcher

// src/observer/watcher.js

import from "./dep";

// 全域性變數id 每次new watcher都會自增

let id = 0;

export default class watcher

// 例項化就會預設呼叫get方法

this.get();

} get()

// 把dep放到deps裡面 同時保證同乙個dep只被儲存到watcher一次 同樣的 同乙個watcher也只會儲存在dep一次

adddep(dep)

} // 這裡簡單的就執行以下get方法 之後涉及到計算屬性就不一樣了

update()

}

watcher 在呼叫 getter 方法前後分別把自身賦值給 dep.target 方便進行依賴收集 update 方法用來更新

6.完善 dep

// src/observer/dep.js

// dep和watcher是多對多的關係

// 每個屬性都有自己的dep

let id = 0; //dep例項的唯一標識

export default class dep

depend()

} notify()

addsub(watcher)

}// 預設dep.target為null

dep.target = null;

// 棧結構用來存watcher

const targetstack = ;

export function pushtarget(watcher)

export function poptarget()

定義相關的方法把收集依賴的同時把自身也放到 watcher 的 deps 容器裡面去

思考? 這時物件的更新已經可以滿足了 但是如果是陣列 類似 a.push(4) 並不會觸發自動更新 因為我們陣列並沒有收集依賴

7.陣列的依賴收集
// src/observer/index.js

// object.defineproperty資料劫持核心 相容性在ie9以及以上

function definereactive(data, key, value) 屬性a對應的值是乙個陣列 觀測陣列的返回值就是對應陣列的observer例項物件

childob.dep.depend();

if (array.isarray(value)) 這種陣列多層巢狀 陣列包含陣列的情況 那麼我們訪問a的時候 只是對第一層的陣列進行了依賴收集 裡面的陣列因為沒訪問到 所以五大收集依賴 但是如果我們改變了a裡面的第二層陣列的值 是需要更新頁面的 所以需要對陣列遞迴進行依賴收集

if (array.isarray(value)) }}

}return value;

},set(newvalue) ,

});}// 遞迴收集陣列依賴

function dependarray(value)

}}

如果物件屬性的值是乙個陣列 那麼執行 childob.dep.depend()收集陣列的依賴 如果陣列裡面還包含陣列 需要遞迴遍歷收集 因為只有訪問資料觸發了 get 才會去收集依賴 一開始只是遞迴對資料進行響應式處理無法收集依賴 這兩點需要分清

8.陣列的派發更新

// src/observer/array.js

methodstopatch.foreach((method) => 那麼我們使用a.push(4) this就是a ob就是a.__ob__ 這個屬性代表的是該資料已經被響應式觀察過了 __ob__物件指的就是observer例項

const ob = this.__ob__;

let inserted;

switch (method)

if (inserted) ob.observearray(inserted); // 對新增的每一項進行觀測

ob.dep.notify(); //陣列派發更新 ob指的就是陣列對應的observer例項 我們在get的時候判斷如果屬性的值還是物件那麼就在observer例項的dep收集依賴 所以這裡是一一對應的 可以直接更新

return result;

};});

關鍵**就是 ob.dep.notify()

9.渲染更新的思維導圖

這裡放一張 整個 vue 響應式原理的 咱們從資料劫持–>模板解析–>模板渲染–>資料變化檢視自動更新整個流程已經手寫了一遍 尤其是此篇介紹的渲染更新相關的知識點 建議反覆理解原理之後自己動手實現一遍 因為vue 很多核心原理和 api 都跟這裡的知識點相關哈

最後如果覺得本文有幫助 記得點贊三連哦 十分感謝!

手寫Vue2 0原始碼 渲染更新原理

此篇主要手寫 vue2.0 原始碼 渲染更新原理 採用觀察者模式 定義 watcher 和 dep 完成依賴收集和派發更新 從而實現渲染更新.適用人群 沒時間去看官方原始碼或者看原始碼看的比較懵而不想去看的同學 1.定義 watcher src observer watcher.js 全域性變數id...

手寫Vue2 0原始碼 渲染更新原理

前言 此篇主要手寫 vue2.0 原始碼 渲染更新原理 採用觀察者模式 定義 watcher 和 dep 完成依賴收集和派發更新 從而實現渲染更新.適用人群 沒時間去看官方原始碼或者看原始碼看的比較懵而不想去看的同學 正文 我們在這裡模擬更新 settimeout 1000 1.定義 watcher...

vue2 0原始碼學習一(vue原始碼構建過程)

前提知識背景 vue.js的打包構建是基於rollup進行的 1.開啟專案的package.json,在裡面可以看到很多配置項以及命令,今天先學習 的構建,需要關注下圖地方 這裡使用的build命令就是平時在使用vue cli打包的時候觸發的命令,可以看到它其實是執行了乙個node程式,執行scri...