欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入探究Vue中$nextTick的實(shí)現(xiàn)原理

 更新時(shí)間:2023年06月21日 10:51:13   作者:雅伊  
這篇文章主要為大家詳細(xì)介紹Vue中$nextTick的實(shí)現(xiàn)原理,文中的示例代碼講解詳細(xì),對(duì)我們深入了解Vue有一定的幫助,需要的小伙伴可以參考一下

前言

Vue 實(shí)現(xiàn)響應(yīng)式并不是數(shù)據(jù)發(fā)生變化之后 DOM 立即變化,而是按一定的策略進(jìn)行 DOM 的更新。

Vue在修改數(shù)據(jù)后,視圖不會(huì)立刻更新,而是等同一事件循環(huán)中的所有數(shù)據(jù)變化完成之后,再統(tǒng)一進(jìn)行視圖更新。

所以如果你用一個(gè)for循環(huán)來動(dòng)態(tài)改變數(shù)據(jù)100次,實(shí)際上它只會(huì)應(yīng)用最后一次改變,如果沒有這種機(jī)制,DOM就進(jìn)行 100 次的重繪,這固然是一個(gè)很大的開銷。

而這里就涉及 Vue 一個(gè)重要的概念:異步更新隊(duì)列。

如果想要在修改數(shù)據(jù)之后立即獲取更新后的 DOM 可以使用 $nextTick。

今天就來看看 $nextTick 是如何實(shí)現(xiàn)的吧?。?!

JS 運(yùn)行機(jī)制 (Event Loop)

JS 執(zhí)行是單線程的,它是基于事件循環(huán)的。事件循環(huán)大致分為以下幾個(gè)步驟:

  • 所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧(execution context stack)。
  • 主線程之外,還存在一個(gè)"任務(wù)隊(duì)列"(task queue)。只要異步任務(wù)有了運(yùn)行結(jié)果,就在"任務(wù)隊(duì)列"之中放置一個(gè)事件。
  • 一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會(huì)讀取"任務(wù)隊(duì)列",看看里面有哪些事件。那些對(duì)應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。
  • 主線程不斷重復(fù)上面的第三步。

這里主線程的執(zhí)行過程就是一個(gè)tick,而所有的異步結(jié)果都是通過任務(wù)隊(duì)列來調(diào)度。

Loop 分為宏任務(wù)和微任務(wù),無論是執(zhí)行宏任務(wù)還是微任務(wù),完成后都會(huì)進(jìn)入到一下tick,并在兩個(gè)tick之間進(jìn)行UI渲染。

由于Vue DOM更新是異步執(zhí)行的,即修改數(shù)據(jù)時(shí),視圖不會(huì)立即更新,而是會(huì)監(jiān)聽數(shù)據(jù)變化,并緩存在同一事件循環(huán)中,等同一數(shù)據(jù)循環(huán)中的所有數(shù)據(jù)變化完成之后,再統(tǒng)一進(jìn)行視圖更新。為了確保得到更新后的DOM,所以設(shè)置了 Vue.nextTick()方法。

異步執(zhí)行的任務(wù)又分為宏任務(wù)、微任務(wù)

$nextTick

是Vue的核心方法之一,官方文檔解釋如下:

在下次DOM更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個(gè)方法,獲取更新后的DOM。

nextTick 原理

Vue是異步執(zhí)行dom更新的,一旦觀察到數(shù)據(jù)變化,Vue就會(huì)開啟一個(gè)隊(duì)列,然后把在同一個(gè)事件循環(huán) (event loop) 當(dāng)中觀察到數(shù)據(jù)變化的 watcher 推送進(jìn)這個(gè)隊(duì)列。如果這個(gè)watcher被觸發(fā)多次,只會(huì)被推送到隊(duì)列一次。這種緩沖行為可以有效的去掉重復(fù)數(shù)據(jù)造成的不必要的計(jì)算和Dom操作。而在下一個(gè)事件循環(huán)時(shí),Vue會(huì)清空隊(duì)列,并進(jìn)行必要的DOM更新。

當(dāng)你設(shè)置 vm.someData = ‘new value’,DOM 并不會(huì)馬上更新,而是在異步隊(duì)列被清除,也就是下一個(gè)事件循環(huán)開始時(shí)執(zhí)行更新時(shí)才會(huì)進(jìn)行必要的DOM更新。如果此時(shí)你想要根據(jù)更新的 DOM 狀態(tài)去做某些事情,就會(huì)出現(xiàn)問題。為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM ,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback) 。這樣回調(diào)函數(shù)在 DOM 更新完成后就會(huì)調(diào)用。

源碼淺析

nextTick 的實(shí)現(xiàn)單獨(dú)有一個(gè)JS文件來維護(hù)它,在src/core/util/next-tick.js中。

nextTick 源碼主要分為兩塊:能力檢測(cè)和根據(jù)能力檢測(cè)以不同方式執(zhí)行回調(diào)隊(duì)列。

watcher 觸發(fā) nextTick

當(dāng)數(shù)據(jù)發(fā)生變化時(shí) dep 通知 watcher 執(zhí)行 update 更新

/**
 * 根據(jù) watcher 配置項(xiàng),決定接下來怎么走,一般是 queueWatcher
 */
update () {
  /* istanbul ignore else */
  if (this.lazy) {
    // 懶執(zhí)行時(shí)走這里,比如 computed
    // 將 dirty 置為 true,可以讓 computedGetter 執(zhí)行時(shí)重新計(jì)算 computed 回調(diào)函數(shù)的執(zhí)行結(jié)果
    this.dirty = true
  } else if (this.sync) {
    // 同步執(zhí)行,在使用 vm.$watch 或者 watch 選項(xiàng)時(shí)可以傳一個(gè) sync 選項(xiàng),
    // 當(dāng)為 true 時(shí)在數(shù)據(jù)更新時(shí)該 watcher 就不走異步更新隊(duì)列,直接執(zhí)行 this.run 
    // 方法進(jìn)行更新
    // 這個(gè)屬性在官方文檔中沒有出現(xiàn)
    this.run()
  } else {
    // 更新時(shí)一般都這里,將 watcher 放入 watcher 隊(duì)列
    queueWatcher(this)
  }
}

queueWatcher

/**
 * 將 watcher 放入 watcher 隊(duì)列 
 */
export function queueWatcher (watcher: Watcher) {
  const id = watcher.id
  // 如果 watcher 已經(jīng)存在,則跳過,不會(huì)重復(fù)入隊(duì)
  if (has[id] == null) {
    // 緩存 watcher.id,用于判斷 watcher 是否已經(jīng)入隊(duì)
    has[id] = true
    if (!flushing) {
      // 當(dāng)前沒有處于刷新隊(duì)列狀態(tài),watcher 直接入隊(duì)
      queue.push(watcher)
    } else {
      // 已經(jīng)在刷新隊(duì)列了
      // 從隊(duì)列末尾開始倒序遍歷,根據(jù)當(dāng)前 watcher.id 找到它大于的 watcher.id 的位置,然后將自己插入到該位置之后的下一個(gè)位置
      // 即將當(dāng)前 watcher 放入已排序的隊(duì)列中,且隊(duì)列仍是有序的
      let i = queue.length - 1
      while (i > index && queue[i].id > watcher.id) {
        i--
      }
      queue.splice(i + 1, 0, watcher)
    }
    // queue the flush
    if (!waiting) {
      // waiting = false 表示當(dāng)前瀏覽器的異步任務(wù)隊(duì)列沒有 flushSchedulerQueue 
      waiting = true
      if (process.env.NODE_ENV !== 'production' && !config.async) {
        // 直接去刷新 watcher 調(diào)度隊(duì)列 
        // 一般不會(huì)走這兒,Vue 默認(rèn)是異步執(zhí)行,如果改為同步執(zhí)行,性能會(huì)大打折扣
        flushSchedulerQueue()
        return
      }
      /**
       *   熟悉的 nextTick => vm.$nextTick、Vue.nextTick
       *   1、將 回調(diào)函數(shù)(flushSchedulerQueue) 放入 callbacks 數(shù)組
       *   2、通過 pending 控制向?yàn)g覽器任務(wù)隊(duì)列中添加 flushCallbacks 函數(shù)
       */
      nextTick(flushSchedulerQueue)
    }
  }
}

watcher 更新時(shí) watcher 依次入隊(duì),避免 watcher 重復(fù)入隊(duì)

$nextTick 本質(zhì)是 promise

export function nextTick(cb? Function, ctx: Object) {
    let _resolve
    // cb 即為傳入的 flushSchedulerQueue函數(shù),會(huì)統(tǒng)一處理壓入callbacks數(shù)組
    // callbacks也就是異步操作隊(duì)列
    callbacks.push(() => {
        if(cb) {
            try {
                cb.call(ctx)  // 調(diào)用 flushSchedulerQueue 函數(shù),將其放入 callbacks異步隊(duì)列
            } catch(e) {
                handleError(e, ctx, 'nextTick')
            }
        } else if (_resolve) {
            _resolve(ctx)
        }
    })
    // pending 為false 說明本輪事件循環(huán)中沒有執(zhí)行過timerFunc()
    if(!pending) {
        pending = true
        timerFunc()
    }
    // 當(dāng)不傳入 cb 參數(shù)時(shí),提供一個(gè)promise化的調(diào)用 
    if(!cb && typeof Promise !== 'undefined') {
      // 如nextTick().then(() => {})
      // 當(dāng)_resolve執(zhí)行時(shí),就會(huì)跳轉(zhuǎn)到then邏輯中
        return new Promise(resolve => {
            _resolve = resolve
        })
    }
}

next-tick.js 對(duì)外暴露了 nextTick 這個(gè)參數(shù),所以每次調(diào)用 Vue.nextTick 時(shí):

會(huì)把傳入的回調(diào)函數(shù) cb 壓入 callbacks 數(shù)組執(zhí)行 timerFunc 函數(shù),延遲調(diào)用 flushCallbacks 函數(shù)遍歷執(zhí)行 callbacks 數(shù)組中的所有函數(shù)

這里的 callbacks 沒有直接在 nextTick 中執(zhí)行回調(diào)函數(shù)的原因是保證在同一個(gè) tick 內(nèi)多次執(zhí)行nextTick,不會(huì)開啟多個(gè)異步任務(wù),而是把這些異步任務(wù)都?jí)撼梢粋€(gè)同步任務(wù),在下一個(gè) tick 執(zhí)行完畢。

MutationObserver

先簡(jiǎn)單介紹下 MutationObserver:MO 是 HTML5 中的 API,用于監(jiān)視 DOM 變動(dòng)的接口,它可以用于監(jiān)控任何 DOM 節(jié)點(diǎn)的變更如子節(jié)點(diǎn)的刪除、屬性的修改、文本內(nèi)容修改等。

調(diào)用過程是要先給它綁定回調(diào),得到 MO 實(shí)例,這個(gè)回調(diào)會(huì)在 MO 實(shí)例監(jiān)聽到變動(dòng)時(shí)觸發(fā)。 這里 MO 的回調(diào)是放在microtask中執(zhí)行的。

// 創(chuàng)建MO實(shí)例
const observer = new MutationObserver(callback)
const textNode = '想要監(jiān)聽的Don節(jié)點(diǎn)'
observer.observe(textNode, {
  characterData: true // 說明監(jiān)聽文本內(nèi)容的修改
})

timerFunc

由于宏任務(wù)耗費(fèi)的時(shí)間是大于微任務(wù)的,所以在瀏覽器支持的情況下,優(yōu)先使用微任務(wù)。如果瀏覽器不支持微任務(wù),再使用宏任務(wù)。

源碼路徑位于:src\core\util\next-tick.js

/**
 * flushCallbacks 做了三件事:
 *   1、將 pending 置為 false  表示下一個(gè) flushCallbacks() 可以進(jìn)入瀏覽器異步任務(wù)隊(duì)列
 *   2、清空 callbacks 數(shù)組
 *   3、執(zhí)行 callbacks 數(shù)組中的所有函數(shù)(比如 flushSchedulerQueue、用戶調(diào)用 nextTick 傳遞的回調(diào)函數(shù))
 */
// 對(duì)callbacks進(jìn)行遍歷,然后執(zhí)行相應(yīng)的回調(diào)函數(shù)
function flushCallbacks () {
    pending = false
    // 這里拷貝的原因是:
    // 有的cb 執(zhí)行過程中又會(huì)往 callbacks 中加入內(nèi)容
    // 比如 $nextTick的回調(diào)函數(shù)里還有$nextTick
    // 后者的應(yīng)該放到下一輪的nextTick 中執(zhí)行
    // 所以拷貝一份當(dāng)前的,遍歷執(zhí)行完當(dāng)前的即可,避免無休止的執(zhí)行下去
    const copies = callbcks.slice(0)
    callbacks.length = 0 // callbacks里面的函數(shù)
    for(let i = 0; i < copies.length; i++) {
        copies[i]() // 執(zhí)行 callbacks 數(shù)組中的每一個(gè)函數(shù)
    }
}
let timerFunc // 異步執(zhí)行函數(shù) 用于異步延遲調(diào)用 flushCallbacks 函數(shù)
// 優(yōu)先使用 Promise  首選 Promise.resolve().then()
if(typeof Promise !== 'undefined' && isNative(Promise)) {
    const p = Promise.resolve()
   // 首選 Promise.resolve().then()
    timerFunc = () => {
        // 在 微任務(wù)隊(duì)列 中放入 flushCallbacks 函數(shù) 
        p.then(flushCallbacks)
        // IOS 的UIWebView, Promise.then 回調(diào)被推入 microTask 隊(duì)列,但是隊(duì)列可能不會(huì)如期執(zhí)行
        // 因此,添加一個(gè)空計(jì)時(shí)器強(qiáng)制執(zhí)行 microTask
        if(isIOS) setTimeout(noop)
    }
    isUsingMicroTask = true
} else if(!isIE && typeof MutationObserver !== 'undefined' && (isNative(MutationObserver) || MutationObserver.toString === '[object MutationObserverConstructor]')) {
    // 當(dāng) 原生 Promise 不可用時(shí),使用 原生 MutationObserver
    let counter = 1
    // 創(chuàng)建MO實(shí)例,監(jiān)聽到DOM變動(dòng)后會(huì)執(zhí)行回調(diào)flushCallbacks
    const observer = new MutationObserver(flushCallbacks)
    const textNode = document.createTextNode(String(counter))
    observer.observe(textNode, {
        characterData: true // 設(shè)置true 表示觀察目標(biāo)的改變
    })
    // 每次執(zhí)行timerFunc 都會(huì)讓文本節(jié)點(diǎn)的內(nèi)容在 0/1之間切換
    // 切換之后將新值復(fù)制到 MO 觀測(cè)的文本節(jié)點(diǎn)上
    // 節(jié)點(diǎn)內(nèi)容變化會(huì)觸發(fā)回調(diào)
    timerFunc = () => {
        counter = (counter + 1) % 2
        textNode.data = String(counter) // 觸發(fā)回調(diào)
    }
    isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
   // setImmediate 宏任務(wù)隊(duì)列,  setImmediate 性能優(yōu)于 setTimeout 將flushCallbacks 放入瀏覽器的異步任務(wù)隊(duì)列
    timerFunc = () => {
        setImmediate(flushCallbacks)
    }
} else {
    timerFunc = () => {
        setTimeout(flushCallbacks, 0)
    }
}

關(guān)鍵在于timeFunc(),該函數(shù)起到延遲執(zhí)行的作用。

nextTick 的目的就是產(chǎn)生一個(gè)回調(diào)函數(shù)加入 task 或者 microtask 中,當(dāng)前棧執(zhí)行完以后(可能中間還有別的排在前面的函數(shù))調(diào)用該回調(diào)函數(shù),起到了異步觸發(fā)(即下一個(gè)tick時(shí)觸發(fā))的目的。

timeFunc() 有四種實(shí)現(xiàn):

1.promise:

如果瀏覽器支持Promise,那么就用 Promise.then 的方式來延遲函數(shù)調(diào)用,Promise.then() 可以將函數(shù)延遲到當(dāng)前函數(shù)調(diào)用棧最末端,也就是函數(shù)調(diào)用棧最后調(diào)用該函數(shù)。從而做到延遲

2.MutationObserver

MutationObserver 是H5 新加的一個(gè)功能,其功能是監(jiān)聽 DOM 節(jié)點(diǎn)的變動(dòng),在所有 DOM 變動(dòng)完成后,執(zhí)行回調(diào)函數(shù)。

3.setImmediate、setTimeout

利用 setImmediate、setTimeout 的延遲原理,setTimeout(func, 0)會(huì)將func函數(shù)延遲到下一次函數(shù)調(diào)用棧的開始,也就是當(dāng)前函數(shù)執(zhí)行完畢后再執(zhí)行該函數(shù),因此完成了延遲功能。

**而 setImmediate 性能優(yōu)于 setTimeout **

延遲調(diào)用優(yōu)先級(jí)如下:

Promise.then > MutationObserver > setImmediate > setTimeout

為什么優(yōu)先使用 microtack

JS 的 event loop 執(zhí)行時(shí)會(huì)區(qū)分 task 和 microtask,引擎在每個(gè) task 執(zhí)行完畢,從隊(duì)列中取下一個(gè) task 來執(zhí)行之前,會(huì)先執(zhí)行完所有 microtask 隊(duì)列中的 microtask。

setTimeout 回調(diào)會(huì)被分配到一個(gè)新的 task 中執(zhí)行,而 Promise 的 resolver、MutationObserver 的回調(diào)都會(huì)被安排到一個(gè)新的 microtask 中執(zhí)行,會(huì)比 setTimeout 產(chǎn)生的 task 先執(zhí)行。

要?jiǎng)?chuàng)建一個(gè)新的 microtask,優(yōu)先使用 Promise,如果瀏覽器不支持,再嘗試 MutationObserver。

實(shí)在不行,只能用 setTimeout 創(chuàng)建 task 了。

為啥要用 microtask? 根據(jù) HTML Standard,在每個(gè) task 運(yùn)行完以后,UI 都會(huì)重渲染,那么在 microtask 中就完成數(shù)據(jù)更新,當(dāng)前 task 結(jié)束就可以得到最新的 UI 了。

反之如果新建一個(gè) task 來做數(shù)據(jù)更新,那么渲染就會(huì)進(jìn)行兩次。

flushCallbacks

依次執(zhí)行callbacks中的函數(shù)

/**
 * 做了三件事:
 *   1、將 pending 置為 false  表示下一個(gè) flushCallbacks() 可以進(jìn)入瀏覽器異步任務(wù)隊(duì)列
 *   2、清空 callbacks 數(shù)組
 *   3、執(zhí)行 callbacks 數(shù)組中的所有函數(shù)(比如 flushSchedulerQueue、用戶調(diào)用 nextTick 傳遞的回調(diào)函數(shù))
 */
function flushCallbacks () {
  // 微任務(wù)隊(duì)列中只能有一個(gè) flushCallbacks()
  pending = false
  const copies = callbacks.slice(0) // 清空 callbacks 數(shù)組
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

callbacks 異步隊(duì)列中存放了 flushSchedulerQueue 函數(shù),

在 flashcallbacks() 刷新隊(duì)列的過程中依次執(zhí)行 callbacks 數(shù)組中的 flushSchedulerQueue 函數(shù)

flushSchedulerQueue

刷新隊(duì)列,保證了 watcher 的父子關(guān)系順序,依次執(zhí)行 watcher 的 run 方法

function flushSchedulerQueue () {
  currentFlushTimestamp = getNow()
  //  flushing = true 表示 watcher 隊(duì)列正在被刷新
  flushing = true
  let watcher, id
  // 確保 watcher 的先后順序
  // watcher 隊(duì)列排序  watcher 的id 由小到大有序遞增  保證組件更新順序  
  // 父組件的 watcher 先于子組件的 watcher 更新
  // 用戶 watcher 先于 渲染 watcher 更新
  // 父組件的 watcher 在執(zhí)行時(shí) 子組件的 watcher 銷毀 可以跳過子組件的執(zhí)行 
  queue.sort((a, b) => a.id - b.id)
  //  for 循環(huán)遍歷 watcher 隊(duì)列  依次執(zhí)行 watcher 的 run 方法
  // queue.length 動(dòng)態(tài)計(jì)算 確保是最新的隊(duì)列
  for (index = 0; index < queue.length; index++) {
    // 拿出當(dāng)前索引的 watcher
    watcher = queue[index]
    // 首先執(zhí)行 brfore 鉤子  執(zhí)行beforeUpdate()
    if (watcher.before) {
      watcher.before() // watcher 實(shí)例化時(shí) 傳入的 before 方法
    }
    // 清空緩存 表示當(dāng)前 watcher 已經(jīng)被執(zhí)行  當(dāng)該 watcher 再次入隊(duì)時(shí)可以進(jìn)入
    id = watcher.id
    has[id] = null
    // 執(zhí)行 watcher 的run() 
    watcher.run()
    if (process.env.NODE_ENV !== 'production' && has[id] != null) {
      circular[id] = (circular[id] || 0) + 1
      if (circular[id] > MAX_UPDATE_COUNT) {
        warn(
          'You may have an infinite update loop ' + (
            watcher.user
              ? `in watcher with expression "${watcher.expression}"`
              : `in a component render function.`
          ),
          watcher.vm
        )
        break
      }
    }
  }
  // keep copies of post queues before resetting state
  const activatedQueue = activatedChildren.slice()
  const updatedQueue = queue.slice()
  resetSchedulerState()
  // call component updated and activated hooks
  callActivatedHooks(activatedQueue)
  callUpdatedHooks(updatedQueue)
  // devtool hook
  /* istanbul ignore if */
  if (devtools && config.devtools) {
    devtools.emit('flush')
  }
}

flushSchedulerQueue() 主要負(fù)責(zé)依次執(zhí)行 queue 數(shù)組中每個(gè) watcher 的 run 方法,從而進(jìn)入更新階段。

刷新隊(duì)列,由 flushCallbacks 函數(shù)負(fù)責(zé)調(diào)用,主要做了如下兩件事:

  • 更新 flushing 為 ture,表示正在刷新隊(duì)列,在此期間往隊(duì)列中 push 新的 watcher 時(shí)需要特殊處理(將其放在隊(duì)列的合適位置)
  • 按照隊(duì)列中的 watcher.id 從小到大排序,保證先創(chuàng)建的 watcher 先執(zhí)行,也配合 第一步
  • 遍歷 watcher 隊(duì)列,依次執(zhí)行 watcher.before、watcher.run,并清除緩存的 watcher

$nextTick 的應(yīng)用場(chǎng)景

1.在Vue生命周期的created()鉤子函數(shù)進(jìn)行的DOM操作一定要放在nextTick的回調(diào)函數(shù)中。

原因是created()鉤子函數(shù)執(zhí)行時(shí)DOM其實(shí)并未進(jìn)行渲染。

2.在數(shù)據(jù)變化后要執(zhí)行的某個(gè)操作,而這個(gè)操作需要使用隨數(shù)據(jù)改變而改變的 DOM 結(jié)構(gòu)的時(shí)候,這個(gè)操作應(yīng)該放在nextTick()的回調(diào)函數(shù)中。

因?yàn)椋篤ue異步執(zhí)行DOM更新,只要觀察到數(shù)據(jù)變化,Vue將開啟一個(gè)隊(duì)列,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)改變,如果同一個(gè) watcher 被多次觸發(fā),只會(huì)被推入到隊(duì)列中一次。

總結(jié)

使用nextTick()是為了可以獲取更新后的DOM 。

觸發(fā)時(shí)機(jī):在同一事件循環(huán)中的數(shù)據(jù)變化后,DOM完成更新,立即執(zhí)行nextTick()的回調(diào)。

同一事件循環(huán)中的代碼執(zhí)行完畢 -> DOM 更新 -> nextTick callback觸發(fā)

Vue 的 nextTick 是如何實(shí)現(xiàn)

  • 將傳遞的回調(diào)函數(shù)放入 callbacks 全局?jǐn)?shù)組中
  • 調(diào)用 timerFunc 函數(shù),在瀏覽器的異步隊(duì)列中放入刷新callbacks(flashcallbacks ) 函數(shù) ,延遲執(zhí)行 (根據(jù)運(yùn)行環(huán)境判斷將flashcallbacks() 放入宏任務(wù)或者是微任務(wù)隊(duì)列, 使得 flashcallbacks 被延遲調(diào)用)
  • 事件循環(huán)到了微任務(wù)或者宏任務(wù),依次遍歷執(zhí)行 callbacks 數(shù)組中的所有函數(shù)

到此這篇關(guān)于深入探究Vue中$nextTick的實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)Vue $nextTick內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue params、query傳參使用詳解

    vue params、query傳參使用詳解

    本篇文章主要介紹了vue params、query傳參使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • 實(shí)例詳解vue.js淺度監(jiān)聽和深度監(jiān)聽及watch用法

    實(shí)例詳解vue.js淺度監(jiān)聽和深度監(jiān)聽及watch用法

    這篇文章主要介紹了vue.js淺度監(jiān)聽和深度監(jiān)聽及watch用法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-08-08
  • vue實(shí)現(xiàn)拖動(dòng)左側(cè)導(dǎo)航欄變大變小

    vue實(shí)現(xiàn)拖動(dòng)左側(cè)導(dǎo)航欄變大變小

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)拖動(dòng)左側(cè)導(dǎo)航欄變大變小,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Vue項(xiàng)目中如何安裝element組件

    Vue項(xiàng)目中如何安裝element組件

    這篇文章主要介紹了Vue項(xiàng)目中如何安裝element組件問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • vue使用原生swiper代碼實(shí)例

    vue使用原生swiper代碼實(shí)例

    這篇文章主要介紹了vue使用原生swiper代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 在vue項(xiàng)目如何使用base64加密

    在vue項(xiàng)目如何使用base64加密

    這篇文章主要介紹了在vue項(xiàng)目如何使用base64加密,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • VUE2.0+Element-UI+Echarts封裝的組件實(shí)例

    VUE2.0+Element-UI+Echarts封裝的組件實(shí)例

    下面小編就為大家分享一篇VUE2.0+Element-UI+Echarts封裝的組件實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue3編寫帶提示的表格組件功能

    vue3編寫帶提示的表格組件功能

    本文介紹了如何使用Vue 3編寫一個(gè)帶提示的表格組件,并假設(shè)每行都有一個(gè)保存按鈕,如果需要全部保存,還會(huì)加上驗(yàn)證,感興趣的朋友一起看看吧
    2025-02-02
  • vue+springboot實(shí)現(xiàn)登錄功能

    vue+springboot實(shí)現(xiàn)登錄功能

    這篇文章主要為大家詳細(xì)介紹了vue+springboot實(shí)現(xiàn)登錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • VUE 使用中踩過的坑

    VUE 使用中踩過的坑

    本篇是我對(duì)vue使用過程中以及對(duì)一些社區(qū)朋友提問我的問題中做的一些總結(jié),感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-02-02

最新評(píng)論