異步佇列渲染
上一篇文章是在vue2.0 中通過Object.defineProperty去攔截并監聽資料變化的回應式原理,這篇文章將會沿著圖譜繼續深入探索,在依賴被通知變化了之后,會觸發vue當中的異步渲染佇列,這里我們就是要研究以下幾點:
- 為什么要設計成異步渲染佇列
- 渲染是如何實作的
- 因為異步渲染佇列而產生的nextTick, 并了解nextTick的使用場景

對上次的代碼做一個改造,使得模板依賴的變數增加時,如下面這樣
let x = ref(1);
let y = ref(1);
let z = ref(1);
onXChanged(() => {
console.log(`x: ${x.value}, y: ${y.value}, z: ${z.value}`);
});
x.value = https://www.cnblogs.com/likme/archive/2021/12/27/2;
y.value = 3;
z.value = 4;
控制臺列印的結果如下:

我們可以看出x, y, z 的更改分別被執行了1次,那這些資料都是存在于模板中的,所以我們會認為這個模板被渲染了3次,那實際專案中, 多次渲染就產生很多的開銷了, 所以從上面的這個例子我們發現,當模板中存在多出變數依賴的時候,每一個變數修改的時候,都會導致一次渲染,是否可以優化?
我們可以思考下實際作業中遇到的場景:
平時我們作業的時候,如果每隔一段時間,也許是5min或者10min,都會有一個策劃向你提出需求時,或者一個新員工向你請教問題,或者一個測驗人員向你提出bug, 如果這種頻率出現很高,那我相信它一定會占用你的正常編碼時間,使得你更加不能專注的完成你的本職作業了,那么我們一般可能都會選擇把他們要做的事情先放到一邊,讓他們等一等,和自己約定一個時間,也許是45分鐘或者1個小時,那么可以讓自己在這段時間更加專注自己的本職作業,然后再去處理其他的事情,
其實vue中異步更新佇列, 邏輯也是差不多的,當我們在一個函式塊中包含對多個變數的依賴時,可以將這些依賴放入一個佇列中,等到當前函式更新一次完成后,在進行批量的渲染操作,下面是具體的實作代碼
(function () {
// let f = n => n * 100 + 200;
let active;
let watch = function (cb) {
active = cb;
active();
active = null;
}
// 需要有個佇列來存盤各項任務
let queue = [];
// 通過微任務方式去執行佇列中的任務
let nextTick = cb => Promise.resolve().then(cb);
// 將任務添加到佇列
let queueJob = job => {
if (!queue.includes(job)) {
queue.push(job)
nextTick(flushJobs)
}
}
// 執行佇列中的任務
let flushJobs = () => {
let job;
while ((job = queue.shift()) !== undefined) {
job()
}
}
// 收集更多依賴
class Dep {
// 依賴收集,將回應依賴添加到deps中
constructor() {
this.deps = new Set();
}
depend() {
if (active) {
this.deps.add(active)
}
}
// 通知依賴更新
notify() {
// 將任務加到佇列中
this.deps.forEach(dep => queueJob(dep))
}
}
let ref = initValue =https://www.cnblogs.com/likme/archive/2021/12/27/> {
let value = initValue;
let dep = new Dep();
return Object.defineProperty({},"value", {
get() {
dep.depend();
return value;
},
set(newValue) {
value = https://www.cnblogs.com/likme/archive/2021/12/27/newValue;
dep.notify()
}
})
}
let x = ref(1);
let y = ref(1);
let z = ref(1);
watch(() => {
console.log(`x: ${x.value}, y: ${y.value}, z: ${z.value}`);
});
x.value = 2;
y.value = 3;
z.value = 4;
})()
測驗結果如下:

這樣我們可以讓所以依賴更新完后,模板重新渲染一次
上面的 nextTick 回傳一個Promise,需要注意的是在下次Dom更新回圈結束之后執行延遲回呼,
在 Vue中會有兩種場景:
- Vue.nextTick([callback,context])
- vm.$nextTick([callback])
- 將回呼延遲到下次DOM更新回圈之后執行,
- 通常用于在修改資料之后使用這個方法,在回呼中獲取更新后的DOM
- 實體中的方法會將callback的this 會自動系結到實體上
- 在生命周期鉤子函式中mounted和updated直接執行的代碼并不能保證子組件有完全的掛載或者更新,這個時候我們可以使用this.$nextTick(function(){})在整個視圖都渲染完成后進行一些操作,這個程序是可靠的,
總結
這篇文章主要是對Vue異步渲染佇列的研究,我們可以看出主要是對于模板性能的優化,所以產生了異步渲染佇列的概念,同樣產生了Vue.nextTick 的api,我們可以通過api去處理在模板更心之后,或者子組件更i性能后的邏輯,轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/399523.html
標籤:其他
