最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

全面解析Vue中的$nextTick

 更新時(shí)間:2020年12月24日 08:36:33   作者:OLong  
這篇文章主要介紹了Vue中的$nextTick的相關(guān)資料,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下

當(dāng)在代碼中更新了數(shù)據(jù),并希望等到對應(yīng)的Dom更新之后,再執(zhí)行一些邏輯。這時(shí),我們就會(huì)用到$nextTick

funcion callback(){
 //等待Dom更新,然后搞點(diǎn)事。
}
$nextTick(callback);

官方文檔對nextTick的解釋是:

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

那么,Vue是如何做的這一點(diǎn)的,是不是在調(diào)用修改Dom的Api之后(appendChild, textContent = "xxxxx" 諸如此類),調(diào)用了我們的回調(diào)函數(shù)?
實(shí)際上發(fā)生了什么呢。

源碼

nextTick的實(shí)現(xiàn)邏輯在這個(gè)文件里:

vue/src/core/util/next-tick.js

我們調(diào)用的this.$nextTick實(shí)際上是這個(gè)方法:

export function nextTick (cb?: Function, ctx?: Object) {
 let _resolve
 callbacks.push(() => {
  if (cb) {
   try {
    cb.call(ctx)
   } catch (e) {
    handleError(e, ctx, 'nextTick')
   }
  } else if (_resolve) {
   _resolve(ctx)
  }
 })
 if (!pending) {
  pending = true
  timerFunc()
 }
 // $flow-disable-line
 if (!cb && typeof Promise !== 'undefined') {
  return new Promise(resolve => {
   _resolve = resolve
  })
 }
}

可以看到

  1. 回調(diào)函數(shù)被存放到了一個(gè)數(shù)組里:callbacks。
  2. 如果沒有傳遞回調(diào)函數(shù),這個(gè)方法會(huì)返回一個(gè)Promise,然后吧reslove當(dāng)成回調(diào)函數(shù)放到flushCallbacks中。所以文檔解釋了把本該當(dāng)成回調(diào)函數(shù)的callbacks放到then里的用法。
  3. 然后,有一個(gè)變量叫pending,如果不在pending中,則執(zhí)行函數(shù)timerFunc。而且pending默認(rèn)等于false。
  4. flushCallbacks這個(gè)函數(shù)會(huì)一口氣執(zhí)行所有回調(diào)函數(shù)。

timerFunc

timerFunc定義在這里

可以看到timerFunc是在一個(gè)已resolve了的Promise的then 中執(zhí)行了flushCallbacks.

利用了js事件循環(huán)的微任務(wù)的機(jī)制

所以,每當(dāng)我們調(diào)用$nextTick,如果pending為false,就會(huì)調(diào)用timerFunc,然后timerFunc會(huì)把flushCallbacks給塞到事件循環(huán)的隊(duì)尾,等待被調(diào)用。

if (typeof Promise !== 'undefined' && isNative(Promise)) {
 const p = Promise.resolve()
 timerFunc = () => {
  p.then(flushCallbacks)
 }
}

flushCallbacks

然后在這個(gè)文件里還有一個(gè)函數(shù)叫:flushCallbacks
用來把保存的回調(diào)函數(shù)給全執(zhí)行并清空。

function flushCallbacks () {
 pending = false
 const copies = callbacks.slice(0)
 callbacks.length = 0
 for (let i = 0; i < copies.length; i++) {
  copies[i]()
 }
}

pending

什么時(shí)候pending為true呢?

從timerFunc被調(diào)用到flushCallbacks被調(diào)用期間pending為true

即一個(gè)事件循環(huán)周期

在pending期間加入的回調(diào)函數(shù),會(huì)被已經(jīng)等待執(zhí)行的flushCallbacks函數(shù)給執(zhí)行。

核心機(jī)制

看完源碼,發(fā)現(xiàn)除了利用了一個(gè)微任務(wù)的機(jī)制,和Dom更新一點(diǎn)關(guān)系都沒有哇。

其實(shí)調(diào)用nextTick的不僅是開發(fā)者,Vue更新Dom時(shí),也用到了nextTick。

開發(fā)者更新綁定的數(shù)據(jù)之后,Vue就會(huì)立刻調(diào)用nextTick,把更新Dom的回調(diào)函數(shù)作為微任務(wù)塞到事件循環(huán)里去。

于是,在微任務(wù)隊(duì)列中,開發(fā)者調(diào)用的nextTick的回調(diào)函數(shù),就一定在更行Dom的回調(diào)函數(shù)之后執(zhí)行了。

但是問題又來了,根據(jù)瀏覽器的渲染機(jī)制,渲染線程是在微任務(wù)執(zhí)行完成之后運(yùn)行的。渲染線程沒運(yùn)行,怎么拿到Dom呢?

因?yàn)?,渲染線程只是把Dom樹渲染成UI而已,Vue更新Dom之后,在Dom樹里,新的Dom節(jié)點(diǎn)已經(jīng)存在了,js線程就已經(jīng)可以拿到新的Dom了。除非開發(fā)者讀取Dom的計(jì)算屬性,觸發(fā)了強(qiáng)制重流渲染線程才會(huì)打斷js線程。

總結(jié)

  1. 首先timerFunc函數(shù)負(fù)責(zé)把回調(diào)函數(shù)們都丟到事件循環(huán)的隊(duì)尾
  2. 然后,nextTick函數(shù)負(fù)責(zé)把回調(diào)函數(shù)們都保存起來。
  3. 調(diào)用nextTick函數(shù)時(shí)會(huì)調(diào)用timerFunc函數(shù)
  4. Vue更新Dom也會(huì)使用nextTick,而且在開發(fā)者調(diào)用nextTick之前。
  5. 因?yàn)?中的先后關(guān)系和事件循環(huán)的隊(duì)列性質(zhì),確保了開發(fā)者的nextTick的回調(diào)一定在Dom更新之后

以上就是解析Vue中的$nextTick的詳細(xì)內(nèi)容,更多關(guān)于Vue中的$nextTick的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue 按鈕 權(quán)限控制介紹

    vue 按鈕 權(quán)限控制介紹

    這篇文章主要介紹了vue 按鈕 權(quán)限控制,在日常項(xiàng)目中,會(huì)碰到需要根據(jù)后臺(tái)接口返回的數(shù)據(jù),來判斷當(dāng)前用戶的操作權(quán)限,必須當(dāng)有刪除權(quán)限時(shí),就顯示刪除按鈕,下面我們就來了解一下具體的解決方法,需要的朋友也可以參考一下
    2021-12-12
  • Vue中定義全局變量與常量的各種方式詳解

    Vue中定義全局變量與常量的各種方式詳解

    Vue.js 如何添加全局常量或變量? 這是最近一個(gè)同事問的問題,發(fā)現(xiàn)很多朋友對這塊不熟悉,所以下面這篇文章主要給大家介紹了關(guān)于Vue中定義全局變量與常量的各種方式,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-08-08
  • 快速解決Error: error:0308010C:digital envelope routines::unsupported的三種解決方案

    快速解決Error: error:0308010C:digital envelope ro

    因?yàn)?nbsp;node.js V17版本中最近發(fā)布的OpenSSL3.0, 而OpenSSL3.0對允許算法和密鑰大小增加了嚴(yán)格的限制,下面通過本文給大家分享快速解決Error: error:0308010C:digital envelope routines::unsupported的三種解決方案,感興趣的朋友一起看看吧
    2024-02-02
  • vue3實(shí)現(xiàn)局部頁面刷新效果的示例詳解

    vue3實(shí)現(xiàn)局部頁面刷新效果的示例詳解

    這篇文章主要為大家詳細(xì)介紹了vue3如何采用 App.vue定義全局變量與方法并實(shí)現(xiàn)局部頁面刷新效果,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2024-01-01
  • Element實(shí)現(xiàn)動(dòng)態(tài)增加多個(gè)輸入框并校驗(yàn)

    Element實(shí)現(xiàn)動(dòng)態(tài)增加多個(gè)輸入框并校驗(yàn)

    本文主要介紹了Element實(shí)現(xiàn)動(dòng)態(tài)增加多個(gè)輸入框并校驗(yàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Vue 3 中使用 OpenLayers 實(shí)時(shí)顯示 zoom 及四角坐標(biāo)的實(shí)現(xiàn)代碼

    Vue 3 中使用 OpenLayers 實(shí)時(shí)顯示 zoom 

    本文介紹了如何在 Vue 3 中使用 OpenLayers 來獲取地圖的 zoom 值以及四角坐標(biāo)信息,并實(shí)時(shí)更新數(shù)據(jù),這種方式可以用于 GIS 應(yīng)用開發(fā),幫助用戶更好地了解當(dāng)前地圖范圍,感興趣的朋友一起看看吧
    2025-04-04
  • vue-cli結(jié)合Element-ui基于cropper.js封裝vue實(shí)現(xiàn)圖片裁剪組件功能

    vue-cli結(jié)合Element-ui基于cropper.js封裝vue實(shí)現(xiàn)圖片裁剪組件功能

    這篇文章主要介紹了vue-cli結(jié)合Element-ui基于cropper.js封裝vue實(shí)現(xiàn)圖片裁剪組件功能,本文圖文并茂給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2018-03-03
  • 基于Vue3創(chuàng)建一個(gè)簡單的倒計(jì)時(shí)組件

    基于Vue3創(chuàng)建一個(gè)簡單的倒計(jì)時(shí)組件

    這篇文章主要給大家介紹了基于Vue3創(chuàng)建一個(gè)簡單的倒計(jì)時(shí)組件的代碼示例,文中通過代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-11-11
  • vue element upload組件 file-list的動(dòng)態(tài)綁定實(shí)現(xiàn)

    vue element upload組件 file-list的動(dòng)態(tài)綁定實(shí)現(xiàn)

    這篇文章主要介紹了vue element upload組件 file-list的動(dòng)態(tài)綁定實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • VUE實(shí)現(xiàn)Studio管理后臺(tái)之鼠標(biāo)拖放改變窗口大小

    VUE實(shí)現(xiàn)Studio管理后臺(tái)之鼠標(biāo)拖放改變窗口大小

    這篇文章主要介紹了VUE實(shí)現(xiàn)Studio管理后臺(tái)之鼠標(biāo)拖放改變窗口大小 的相關(guān)知識,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的工作或?qū)W習(xí)具有一定的參考價(jià)值,需要的朋友可以參考下
    2020-03-03

最新評論

靖边县| 黄石市| 阿勒泰市| 鲁甸县| 南汇区| 双桥区| 达日县| 腾冲县| 阿瓦提县| 集安市| 广德县| 黄梅县| 遂平县| 水城县| 丹阳市| 永和县| 乡城县| 永顺县| 灵丘县| 伊宁市| 略阳县| 邹城市| 青铜峡市| 合江县| 龙口市| 博客| 莒南县| 留坝县| 东阿县| 晋江市| 都江堰市| 西和县| 巢湖市| 栾城县| 东乌珠穆沁旗| 西安市| 五原县| 通榆县| 舒城县| 古浪县| 内江市|