vue->$nextTick
引用官方的話:為了在資料變化之後等待 Vue 完成更新 DOM ,可以在資料變化之後立即使用 Vue.nextTick(callback)
- ex1
<div>
<button @click="add">add</button>
<div ref="tagName">{{name}}</div>
</div>
複製程式碼
data () {
return {
name: merlo
}
}
methods: {
add() {
this.name = 'iron man'
console.log(this.$ref['tagName'].innerHTML) // 仍然是merlo
this.$nextTick((v) => {
console.log(this.$ref['tagName'].innerHTML) // 已經變成iron man
})
}
}
複製程式碼
- ex2
<div>
<button @click="add">add</button>
<div ref="tagName" :style="css">{{info}}</div>
</div>
複製程式碼
data() {
return {
css: { height: '666px'}
}
}
methods: {
add() {
this.css = { height: '666666px' }
console.log(this.$ref['tagName'].offsetHeight) // 依然666px
this.$nextTick((v) => {
console.log(this.$ref['tagName'].offsetHeight) // 變成666666px
})
}
}
複製程式碼
相關原理
在 Vue 2.4 之前都是使用的 microtasks,但是 microtasks 的優先順序過高,在某 些情況下可能會出現比事件冒泡更快的情況,但如果都使用 macrotasks 又可能會出現 渲染的效能問題。所以在新版本中,會預設使用 microtasks,但在特殊情況下會使用 macrotasks,比如 v-on。
macrotasks: microtasks的作用是用來排程應在當前執行的指令碼執行結束後立即執行的任務。 例如響應事件、或者非同步操作,以避免付出額外的一個task的費用。
- I/O
- setTimeout
- setInterval
- setImmediate
- requestAnimationFrame
- UI rendering
microtasks: 就是常說的任務佇列task queue
,作用是為了讓瀏覽器能夠從內部獲取javascript / dom的內容並確保執行棧能夠順序進行。
- process.nextTick
- Promises
- Object.observe
- MutationObserver
ex:
setTimeout(function(){
console.log(1)
},0);
new Promise(function(resolve){
console.log(2)
for( var i=100000 ; i>0 ; i-- ){
i==1 && resolve()
}
console.log(3)
}).then(function(){
console.log(4)
});
console.log(5);
// 以上列印結果 2,3,5,4,1
複製程式碼
tip:
在__Microsoft Edge__, Firefox 40__, __iOS Safari 以及 desktop Safari 8.0.8 中setTimeout會先於Promise
參考資料:
- macrotask within an event loop context
- 知乎-Promise的佇列與setTimeout的佇列有何關聯?
- 通過microtasks和macrotasks看JavaScript非同步任務執行順序
- 阮一峰-JavaScript 執行機制詳解:再談Event Loop