參考資料: 掘金小冊 《剖析Vue.js內部運行機制》
<div id="app">
<div>{{ number }}</div>
<div>{{ hahaha }}</div>
</div>
<div id="app2">
<div>{{ number }}</div>
<div>{{ hahaha }}</div>
</div>
const data = {
message: 'Hello Vue!',
a: 1
}
const app = new Vue({
el: '#app',
data: data
})
const app2 = new Vue({
el: '#app2',
data: data
})
一個視圖(
<div id="app">
<div>{{ number }}</div>
<div>{{ hahaha }}</div>
</div>
)對應一個watcher watcher在編譯模板時候生成 watcher生成的時候會調用使用到的數據的get方法 從而將該watcher放到dep中
number: 0 dep1
msg: 'hahaha' dep2
一個數據對應一個dep
當數據改變時接奈,會調用對應數據的set方法 從而dep.notify->watcher.update
依賴收集的結果為
dep1收集了 watcher1 watcher2
dep2收集了 watcher1 watcher2
例如: 這里number = 1 會dep1.notify->watcher1.update(視圖1#app的更新),watcher2.update(視圖2#app2的更新)
watcher1.update->watcher1.queueWatcher(watcher1)
三個隊列
queue 用于存放watcher
callbacks 用于存放flushScdulerQueueFn【用于存放處理queue的函數】
settimeout隊列【異步隊列】 用于存放flushCallbacksFn【用于存放處理callbacks的函數】
queue = []
waiting = false
queueWatcher (watcher) {
queue.push(watcher) //判重加入watcher
if(!waiting) {
waiting = true
nextTick(flushScdulerQueueFn)
}
}
flushScdulerQueueFn() {
//處理queue數組中的每一項 并且調用watcher.run() 處理過的watcher從queue中移除
waiting = false
}
callbacks = []
pending = false
nextTick (cb) {
callbacks.push(cb)
if(!pending) {
pending = true
settimeout(flushCallbacksFn,0)
}
}
flushCallbacksFn () {
pending = false
// 處理callbacks數組中的每一項 并且調用flushScdulerQueueFn
}