關於vue中next和Tick(nextTick)的一點理解

前言

在這以前我是沒有怎麼看過vue源碼的,可是看了源碼後又產生了一些疑問,若是不看源碼我還真沒有任何疑問的去用nextTick,由於我只知道我想獲取更新後的dom我就在裏面寫回調,只管寫準沒錯,有天好奇調試了下代碼就發現了一些疑問....javascript

何時開始本次Tick?

百度搜索event loops能夠看到不少文章,可是看了不少文章都沒讓我知道或者做者沒有去說明何時開始第一次tick,不過也幸運,仍是有人skycity明確說出了,印象中以前掘金有篇文章我在評論裏面也獲得過答案,答案就是從全局script開始執行開始第一輪tickhtml

何時結束本次Tick?

這個也是我根據搜索資料得出結論,當GUI 渲染完後本輪Tick結束,可是在開始渲染以前js 引擎會執行完全部的微任務隊列,新的叫法是jobs,宏任務叫tasksvue

一次tick結束以後幹嗎?

繼續查找事件任務隊列中是否有tasks,若是沒有就靜靜等待非空,若是有就繼續開始第二輪tick,取出tasks執行 我畫了個圖能夠表示下這個過程java

這個結論是我目前以爲正確的,但願有以爲不對的地方能夠評論討論下。

爲何叫next**?

按照官網的解釋git

在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。github

我我的是並不理解這個下次dom更新循環是指的什麼?是跟event loop這個事件循環一個意思嗎?本次dom更新循環是何時開始?何時結束?但願有人知道的解釋下。我以爲執行回調的時機是在下個tick以前執行的,segmentfault

2018.7.21更新:根絕 SHERlocked93 大佬的文章參考以及他的回答,nextTick的回調執行時機實際上是不肯定的,看下面這個圖:瀏覽器

根據上面的圖能夠看到最終回調有可能放入兩個隊列,那被執行的時機就有一下可能:

1:放入微任務隊列,則在本輪tick執行dom

2:放入宏任務隊列,則在下輪tick或者下下輪,或者下n輪 第二種爲何不肯定呢?由於不知道放入隊列時前面有幾個任務在排隊,可能之後n個計時器,而宏任務不像微任務一次所有執行完,宏任務是一個tick只執行一個任務,每一個任務都在不一樣的tick,因此時機不定,可是確定是在本輪tick以後異步

下面的代碼我只走了支持Promsie的瀏覽器的過程,此時是在本輪tick執行 假設html中有這行代碼 <div ref="msg">{{msg}}</div> 咱們在mounted裏面執行

this.msg = 'hello';
this.$nextTick(()=>{
    console.log(this.$refs.msg.innerHTML)
})
複製代碼

上述代碼在vue裏面的大體以下執行流程以下

經過上面的流程分析,nextTick裏面的回調是在當前時間循環內執行的,並無在下個事件循環執行。so,在下個事件循環執行時dom確實是最新的了,可是回調並無在下個事件循環執行。

總結

1.nextTick裏面的回調是在本輪tick循環中執行的 nextTick裏面的回調是在本輪tick或者下n輪tick中執行的(n=1,2,3...)

2.全部的微任務會在本輪tick中所有執行完

3.任何一個宏任務也就是tasks都不在一個tick中執行,而是在不一樣的tick

4.強烈推薦你們去看下這兩篇文章,寫的很詳細 :

Vue源碼閱讀 - 批量異步更新與nextTick原理

2018.7.26更新:補一篇文章,5星推薦這個

Vue源碼詳解之nextTick:MutationObserver只是浮雲,microtask纔是核心!

參考連接:

理解javascript中的事件循環(EventLoop)

Javascript事件循環機制以及渲染引擎什麼時候渲染UI

從瀏覽器多進程到JS單線程,JS運行機制最全面的一次梳理

相關文章
相關標籤/搜索