Vue2.6中的nextTick方法是什么-創(chuàng)新互聯(lián)

小編給大家分享一下Vue2.6中的nextTick方法是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

創(chuàng)新互聯(lián)從2013年創(chuàng)立,是專(zhuān)業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站建設(shè)、做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元聶拉木做網(wǎng)站,已為上家服務(wù),為聶拉木各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話(huà):18980820575

淺析 Vue 2.6 中的 nextTick 方法。

事件循環(huán)

JS 的 事件循環(huán)任務(wù)隊(duì)列 其實(shí)是理解 nextTick 概念的關(guān)鍵。
這個(gè)網(wǎng)上其實(shí)有很多優(yōu)質(zhì)的文章做了詳細(xì)介紹,我就簡(jiǎn)單過(guò)過(guò)了。

以下內(nèi)容適用于瀏覽器端 JS,NodeJS 的事件循環(huán)機(jī)制并不相同。

規(guī)范中規(guī)定 task 分為兩大類(lèi): task(macrotask)microtask。

通常認(rèn)為是 task 的任務(wù)源:

setTimeout / setInterval
setImmediate
MessageChannel
I/O
UI rendering

通常認(rèn)為是 microtask 的任務(wù)源:

Promise
process.nextTick
MutationObserver
Object.observe(已廢棄)

簡(jiǎn)單概況:(這里是官方規(guī)范)

  1. 首先開(kāi)始執(zhí)行 script 腳本,直到執(zhí)行上下文棧為空時(shí),開(kāi)始清空 microtask 隊(duì)列里的任務(wù),隊(duì)列嘛,先入先出,出一個(gè)執(zhí)行一個(gè),清空完畢,走事件循環(huán)。

  2. 事件循環(huán):不斷地去取 task 隊(duì)列的中的一個(gè)任務(wù)推入棧中執(zhí)行,并在當(dāng)次循環(huán)里依次清空 microtask 隊(duì)列里的任務(wù),清空之后,可能會(huì)觸發(fā)頁(yè)面更新渲染(由瀏覽器決定)。

  3. 之后重復(fù) 事件循環(huán) 步驟。

nextTick

Vue 中數(shù)據(jù)的變化到 DOM 的更新渲染是一個(gè)異步過(guò)程。
此方法便用于在 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。
使用方法很簡(jiǎn)單:

// 修改數(shù)據(jù)
vm.msg = 'Hello';
// DOM 還沒(méi)有更新
Vue.nextTick(function() {
  // DOM 更新了
});

// 作為一個(gè) Promise 使用
Vue.nextTick().then(function() {
  // DOM 更新了
});

源碼 去除注釋?zhuān)鋵?shí)也只有不到一百來(lái)行,整體還是很容易理解的。

這里劃成 3 個(gè)部分介紹。

模塊變量

介紹 引入的模塊 和 定義的變量。

// noop 空函數(shù),可用作函數(shù)占位符
import { noop } from 'shared/util';

// Vue 內(nèi)部的錯(cuò)誤處理函數(shù)
import { handleError } from './error';

// 判斷是IE/IOS/內(nèi)置函數(shù)
import { isIE, isIOS, isNative } from './env';

// 使用 MicroTask 的標(biāo)識(shí)符
export let isUsingMicroTask = false;

// 以數(shù)組形式存儲(chǔ)執(zhí)行的函數(shù)
const callbacks = [];

// nextTick 執(zhí)行狀態(tài)
let pending = false;

// 遍歷函數(shù)數(shù)組執(zhí)行每一項(xiàng)函數(shù)
function flushCallbacks() {
  pending = false;
  const copies = callbacks.slice(0);
  callbacks.length = 0;
  for (let i = 0; i < copies.length; i++) {
    copies[i]();
  }
}

異步延遲函數(shù)

接下來(lái)是核心的 異步延遲函數(shù)。這里不同的 Vue 版本采用的策略其實(shí)并不相同。

2.6 版本優(yōu)先使用 microtask 作為異步延遲包裝器。

2.5 版本則是 macrotask 結(jié)合 microtask。然而,在重繪之前狀態(tài)改變時(shí)會(huì)有小問(wèn)題(如 #6813)。此外,在事件處理程序中使用 macrotask 會(huì)導(dǎo)致一些無(wú)法規(guī)避的奇怪行為(如#7109,#7153,#7546,#7834,#8109)。

所以 2.6 版本現(xiàn)在又改用 microtask 了,為什么是又呢。。因?yàn)?2.4 版本及之前也是用的 microtask。。。

microtask 在某些情況下也是會(huì)有問(wèn)題的,因?yàn)?microtask 優(yōu)先級(jí)比較高,事件會(huì)在順序事件(如#4521,#6690 有變通方法)之間甚至在同一事件的冒泡過(guò)程中觸發(fā)(#6566)。

// 核心的異步延遲函數(shù),用于異步延遲調(diào)用 flushCallbacks 函數(shù)
let timerFunc;

// timerFunc 優(yōu)先使用原生 Promise
// 原本 MutationObserver 支持更廣,但在 iOS >= 9.3.3 的 UIWebView 中,觸摸事件處理程序中觸發(fā)會(huì)產(chǎn)生嚴(yán)重錯(cuò)誤
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve();
  timerFunc = () => {
    p.then(flushCallbacks);

    // IOS 的 UIWebView,Promise.then 回調(diào)被推入 microtask 隊(duì)列但是隊(duì)列可能不會(huì)如期執(zhí)行。
    // 因此,添加一個(gè)空計(jì)時(shí)器“強(qiáng)制”執(zhí)行 microtask 隊(duì)列。
    if (isIOS) setTimeout(noop);
  };
  isUsingMicroTask = true;

  // 當(dāng)原生 Promise 不可用時(shí),timerFunc 使用原生 MutationObserver
  // 如 PhantomJS,iOS7,Android 4.4
  // issue #6466 MutationObserver 在 IE11 并不可靠,所以這里排除了 IE
} else if (
  !isIE &&
  typeof MutationObserver !== 'undefined' &&
  (isNative(MutationObserver) ||
    // PhantomJS 和 iOS 7.x
    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;

  // 如果原生 setImmediate 可用,timerFunc 使用原生 setImmediate
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
  timerFunc = () => {
    setImmediate(flushCallbacks);
  };
} else {
  // 最后的倔強(qiáng),timerFunc 使用 setTimeout
  timerFunc = () => {
    setTimeout(flushCallbacks, 0);
  };
}

一句話(huà)總結(jié)優(yōu)先級(jí):microtask 優(yōu)先。
Promise > MutationObserver > setImmediate > setTimeout

nextTick 函數(shù)

nextTick 函數(shù)。接受兩個(gè)參數(shù):

  1. cb 回調(diào)函數(shù):是要延遲執(zhí)行的函數(shù);

  2. ctx:指定 cb 回調(diào)函數(shù) 的 this 指向;

Vue 實(shí)例方法 $nextTick 做了進(jìn)一步封裝,把 ctx 設(shè)置為當(dāng)前 Vue 實(shí)例

export function nextTick(cb?: Function, ctx?: Object) {
  let _resolve;

  // cb 回調(diào)函數(shù)會(huì)經(jīng)統(tǒng)一處理壓入 callbacks 數(shù)組
  callbacks.push(() => {
    if (cb) {
      // 給 cb 回調(diào)函數(shù)執(zhí)行加上了 try-catch 錯(cuò)誤處理
      try {
        cb.call(ctx);
      } catch (e) {
        handleError(e, ctx, 'nextTick');
      }
    } else if (_resolve) {
      _resolve(ctx);
    }
  });

  // 執(zhí)行異步延遲函數(shù) timerFunc
  if (!pending) {
    pending = true;
    timerFunc();
  }

  // 當(dāng) nextTick 沒(méi)有傳入函數(shù)參數(shù)的時(shí)候,返回一個(gè) Promise 化的調(diào)用
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve;
    });
  }
}

小結(jié)

整體看過(guò)來(lái),感覺(jué)還是比較好理解的吧~ 2.6 版本相比之前簡(jiǎn)化了一點(diǎn)。

小結(jié)一下,每次調(diào)用 Vue.nextTick(cb) 會(huì)做些什么:
cb 函數(shù)經(jīng)處理壓入 callbacks 數(shù)組,執(zhí)行 timerFunc 函數(shù),延遲調(diào)用 flushCallbacks 函數(shù),遍歷執(zhí)行 callbacks 數(shù)組中的所有函數(shù)。

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

版本差異

其實(shí) Vue 2.4、2.5、2.6 版本的 nextTick 策略都略不一樣。

整體 2.62.4 的比較相似。(仔細(xì)瞅了瞅,基本就是一樣的,2.6 timerFunc 多了個(gè) setImmediate 判斷)

2.5 版本其實(shí)也差不多。。。源碼寫(xiě)法有些不一樣,整體優(yōu)先級(jí)是:Promise > setImmediate > MessageChannel > setTimeout,如果更新是在 v-on 事件處理程序中觸發(fā)的,nextTick 會(huì)優(yōu)先使用 macrotask。

以上是“Vue2.6中的nextTick方法是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線(xiàn),公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。

分享題目:Vue2.6中的nextTick方法是什么-創(chuàng)新互聯(lián)
網(wǎng)址分享:http://muchs.cn/article42/cddjec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃微信小程序、建站公司ChatGPT、企業(yè)網(wǎng)站制作、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)