Vue nextTick的原理解析
使用過Vue的小伙伴們都知道,Vue里的nextTick可以獲取到更新后的DOM, 今天我就來講解下nextTick里面究竟做了什么?
開始講解前,我們需要知道了解一個概念,那就是Event Loop
Event LoopEvent Loop翻譯過來就是事件循環, 一個Event Loop會包括一個或多個task隊列,持續線程會從隊列中取出最早進入隊列的任務進行執行,被取出的任務就叫做macroTask(宏任務), 每個macroTask都有一個任務源, 每個macroTask處理完之后就從隊列中取出下一個時間最早進入的macroTask再重執行
任務源:
``` 1. script 2. 事件 3. Dom交互 4. I/O 5. UI Render 6. setTimeout 7. setInterval 8. requestAnimationFrame .....```
也就是說碰到以上幾種情況就會產生一個macroTask并且推入到隊列中
miscroTask(微任務)執行完每個macroTask之后,主線程會去檢查該macroTask下的microTask是否為空,如果不為空,則按照時間順序從早到晚取出,如果途中有遇到新的microTask, 那么會繼續將該microTask推入到microTask隊列里
UI Render(重點)伴隨著miscroTask隊列的清空,主線程就會執行UI Render, 也就是渲染界面,但是瀏覽器它并不會每次在UI Render任務下一定會渲染界面,視情況而言,現在主流瀏覽器一般都是按照60HZ 也就是16.7ms刷新頻率進行渲染(不是精確估量),一個macroTask通常是小于16.7ms, 所以瀏覽器每次會根據情況進行渲染
總結下一個循環1. 從macroTask隊列里取出最早添加進去的2. 開始執行task, 途中如果遇到新的macroTask,就會將其添加到macroTask隊列的最后面3. 執行完macroTask之后,event loop會去尋找microTask隊列4. 同樣的道理,如果途中遇到新的microTask,將其放入該macroTask下的microTask隊列最后面5. 執行完microTask,會執行UI Render macroTask6. 瀏覽器會根據現有情況決定是否更新DOM,通常是按照60HZ的頻率去更新7. 至此,一個event loop結束了
nextTick我們開始分析nextTick
根據上圖我們看到nextTick的幾種寫法:
1. this.$nextTick(cb) 2. this.$nextTick().then(cb)
所有的cb都會被放入到callbacks數組里,等待一次性調用上圖中我們看到了主要是由timerFunc這個函數來進行調用回調, 那么我們下面來著重介紹這個函數,首先看下源碼
我們可以看到timerFunc在不同情況下不同的賦值情況
首先會判斷瀏覽器是否支持promise屬性, 如果支持, timerFunc就會被賦值成Promise, 這里有個小小的問題,那就是在ios下,雖然是具備Pormise對象,并且會將它推入到microTask隊列里,但是隊列卻不會更新,這個時候需要添加一個macroTask來強制刷新microTask隊列
MutationObserver, 相信很多人并不清楚這個Api, 這是一個能夠監聽DOM變化的API,并且屬于microTask, 優先級低于Promise 在創建一個新的文本節點后,手動更改其文本節點來觸發microTask,
這里會有個小小的問題:
該文本節點渲染成功后,一定能代表其他的DOM渲染成功了嗎?
這是個備選方案, 主要還是因為它是一個微任務,所以才使用它,并不是因為它監聽了DOM
微任務都失敗后, 退而求其次,選擇setImmediate, 這是一個只有高版本IE和Edge瀏覽器才可能擁有的API, 其主要是用于計算大量數據的時候使用
最后就是setTimeout
看到這里,你會不會有疑惑?
上面的代碼并沒有說明nextTick是在監聽DOM更新后才執行的? What????當時腦袋就duang了一下
那么接下來說的就是重中之重
DOM Tree的更新是實時的,DOM Tree的更新是實時的,DOM Tree的更新是實時的, 重要的事說3遍, 這意味著你無需去監聽DOM 更新, 你對DOM的操作是能夠實時得到反饋的,上一行代碼操作了DOM,下一行就能獲取到
那么有人就會產生疑惑了, nextTick究竟是干嘛的?
nextTick的作用是將收集Watcher從隊列中一個個取出,并且更改數據,來一次性渲染DOM, 我們知道操作DOM的代價是昂貴的, 瀏覽器打開一個網頁后會開啟一個進程,進程是由線程組成的,
1. GUI渲染線程2. js引擎線程(主線程)3. EventLoop輪訓處理線程4. 其他線程,例如網絡
跨線程操作代價是昂貴的,所以做到一次性渲染Dom,可以有效的優化性能!!
總結nextTick并不是用來監聽DOM變更,因為DOM變更是能夠實時獲取到的,它的作用是一次性更改數據,并且渲染DOM
以上就是Vue nextTick的原理解析的詳細內容,更多關于Vue nextTick的原理的資料請關注好吧啦網其它相關文章!
相關文章:
