nextTick的實現原理是什么?


在下次DOM更新循環結束之后執行的延遲回調。

根據執行環境分別嘗試采用 用微任務,再是宏任務

Promise的then -> MutationObserver的回調函數 -> setImmediate -> setTimeout 是否存在,找到存在的就調用他childrenRef

作用:
nextTick用於下次Dom更新循環結束之后執行延遲回調,在修改數據之后使用nextTick用於下次Dom更新循環結束之后執行延遲回調,在修改數據之后使用nextTick用於下次Dom更新循環結束之后執行延遲回調,在修改數據之后使用nextTick,則可以在回調中獲取更新后的DOM。

應用場景:
需要在視圖更新之后,基於新的視圖進行操作。

實現原理:
nextTick方法主要是使用了宏任務和微任務,定義了一個異步方法,多次調用nextTick會將方法存入隊列中,通過這個異步方法清空隊列。

 


 

VUE中nextTick實現原理

在vue中有nextTick這個API,官方解釋,它可以在DOM更新完畢之后執行一個回調。
一般使用

this.$nextTick(() => {
    ...
})

一般來說,在對於MVVM框架結構的技術棧是不推薦操作DOM的,但是很多情況下可能會需要操作DOM,特別是一些charts插件等。

所以nextTick就出現了,確保我們所操作的DOM是更新之后的。
那VUE是如何知道DOM什么時候更新完了呢?

VUE源碼:(把里面的注釋都刪掉了)

if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    characterData: true
  })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

步驟:

先判斷Promise

在判斷MutationObserver

在判斷setImmediate

最后setTimeout

整體流程涉及到事件的循環(Event Loop)[暫不在這說]

每次event loop的最后,會有一個UI render,也就是更新DOM

只要讓nextTick里的代碼放在UI render步驟后面執行,就能訪問到更新后的DOM了。

 

又涉及到微任務(microtask)和宏任務(macrotask)

microtask有:Promise、MutationObserver,以及nodejs中的process.nextTick

macrotask有:setTimeout, setInterval, setImmediate, I/O, UI rendering

每一次事件循環都包含一個microtask隊列,在循環結束后會依次執行隊列中的microtask並移除,然后再開始下一次事件循環。

 

vue的nextTick方法的實現原理:

vue用異步隊列的方式來控制DOM更新和nextTick回調先后執行

microtask因為其高優先級特性,能確保隊列中的微任務在一次事件循環前被執行完畢

因為瀏覽器和移動端兼容問題,vue不得不做了microtask向macrotask的兼容(降級)方案

 

原文鏈接:https://blog.csdn.net/guoqiankunmiss/java/article/details/97808703

 

VUE中nextTick實現原理在vue中有nextTick這個API,官方解釋,它可以在DOM更新完畢之后執行一個回調。一般使用
this.$nextTick(() => {...})123一般來說,在對於MVVM框架結構的技術棧是不推薦操作DOM的,但是很多情況下可能會需要操作DOM,特別是一些charts插件等。
所以nextTick就出現了,確保我們所操作的DOM是更新之后的。那VUE是如何知道DOM什么時候更新完了呢?
VUE源碼:(把里面的注釋都刪掉了)
if (typeof Promise !== 'undefined' && isNative(Promise)) {  const p = Promise.resolve()  timerFunc = () => {    p.then(flushCallbacks)    if (isIOS) setTimeout(noop)  }  isUsingMicroTask = true} else if (!isIE && typeof MutationObserver !== 'undefined' && (  isNative(MutationObserver) ||  MutationObserver.toString() === '[object MutationObserverConstructor]')) {  let counter = 1  const observer = new MutationObserver(flushCallbacks)  const textNode = document.createTextNode(String(counter))  observer.observe(textNode, {    characterData: true  })  timerFunc = () => {    counter = (counter + 1) % 2    textNode.data = String(counter)  }  isUsingMicroTask = true} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {  timerFunc = () => {    setImmediate(flushCallbacks)  }} else {  timerFunc = () => {    setTimeout(flushCallbacks, 0)  }}
1234567891011121314151617181920212223242526272829303132步驟:
先判斷Promise在判斷MutationObserver在判斷setImmediate最后setTimeout整體流程涉及到事件的循環(Event Loop)[暫不在這說]
每次event loop的最后,會有一個UI render,也就是更新DOM只要讓nextTick里的代碼放在UI render步驟后面執行,就能訪問到更新后的DOM了。
又涉及到微任務(microtask)和宏任務(macrotask)microtask有:Promise、MutationObserver,以及nodejs中的process.nextTickmacrotask有:setTimeout, setInterval, setImmediate, I/O, UI rendering每一次事件循環都包含一個microtask隊列,在循環結束后會依次執行隊列中的microtask並移除,然后再開始下一次事件循環。
vue的nextTick方法的實現原理:
vue用異步隊列的方式來控制DOM更新和nextTick回調先后執行microtask因為其高優先級特性,能確保隊列中的微任務在一次事件循環前被執行完畢因為瀏覽器和移動端兼容問題,vue不得不做了microtask向macrotask的兼容(降級)方案————————————————版權聲明:本文為CSDN博主「gqkmiss」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/guoqiankunmiss/java/article/details/97808703


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM