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

Vue.nextTick純干貨使用方法詳解

 更新時間:2022年07月08日 17:27:14   作者:井柏然  
這篇文章主要為大家介紹了Vue.nextTick使用方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

用過Vue的朋友多多少少都知道$nextTick~ 在正式講解nextTick之前,我想你應該清楚知道 Vue 在更新 DOM 時是異步執(zhí)行的,因為接下來講解過程會結合組件更新一起講~ 事不宜遲,我們直進主題吧(本文以v2.6.14版本的Vue源碼進行講解)

一、nextTick小測試

你真的了解nextTick嗎?來,直接上題~

<template>
  <div id="app">
    <p ref="name">{{ name }}</p>
    <button @click="handleClick">修改name</button>
  </div>
</template>
<script>
  export default {
  name: 'App',
  data () {
    return {
      name: '井柏然'
    }
  },
  mounted() {
    console.log('mounted', this.$refs.name.innerText)
  },
  methods: {
    handleClick () {
      this.$nextTick(() => console.log('nextTick1', this.$refs.name.innerText))
      this.name = 'jngboran'
      console.log('sync log', this.$refs.name.innerText)
      this.$nextTick(() => console.log('nextTick2', this.$refs.name.innerText))
    }
  }
}
</script>

請問上述代碼中,當點擊按鈕“修改name”時,'nextTick1','sync log','nextTick2'對應的this.$refs.name.innerText分別會輸出什么?注意,這里打印的是DOM的innerText~(文章結尾處會貼出答案)

如果此時的你有非常堅定的答案,那你可以不用繼續(xù)往下看了~但如果你對自己的答案有所顧慮,那不如跟著我,接著往下看。相信你看完,不需要看到答案都能有個肯定的答案了~!

二、nextTick源碼實現(xiàn)

源碼位于core/util/next-tick中??梢詫⑵浞譃?個部分來看,直接上代碼

1. 全局變量

callbacks隊列、pending狀態(tài)

const callbacks = [] // 存放cb的隊列
let pending = false // 是否馬上遍歷隊列,執(zhí)行cb的標志

2. flushCallbacks

遍歷callbacks執(zhí)行每個cb

function flushCallbacks () {
  pending = false // 注意這里,一旦執(zhí)行,pending馬上被重置為false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]() // 執(zhí)行每個cb
  }
}

3. nextTick的異步實現(xiàn)

根據(jù)執(zhí)行環(huán)境的支持程度采用不同的異步實現(xiàn)策略

let timerFunc // nextTick異步實現(xiàn)fn
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  // Promise方案
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks) // 將flushCallbacks包裝進Promise.then中
  }
  isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  // MutationObserver方案
  let counter = 1
  const observer = new MutationObserver(flushCallbacks) // 將flushCallbacks作為觀測變化的cb
  const textNode = document.createTextNode(String(counter)) // 創(chuàng)建文本節(jié)點
  // 觀測文本節(jié)點變化
  observer.observe(textNode, {
    characterData: true
  })
  // timerFunc改變文本節(jié)點的data,以觸發(fā)觀測的回調(diào)flushCallbacks
  timerFunc = () => { 
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
  // setImmediate方案
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  // 最終降級方案setTimeout
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

這里用個真實案例加深對MutationObserver的理解。畢竟比起其他三種異步方案,這個應該是大家最陌生的

const observer = new MutationObserver(() => console.log('觀測到文本節(jié)點變化'))
const textNode = document.createTextNode(String(1))
observer.observe(textNode, {
    characterData: true
})
console.log('script start')
setTimeout(() => console.log('timeout1'))
textNode.data = String(2) // 這里對文本節(jié)點進行值的修改
console.log('script end')

知道對應的輸出會是怎么樣的嗎?

script start、script end會在第一輪宏任務中執(zhí)行,這點沒問題

setTimeout會被放入下一輪宏任務執(zhí)行

MutationObserver是微任務,所以會在本輪宏任務后執(zhí)行,所以先于setTimeout

結果如下圖:

4. nextTick方法實現(xiàn)

cbPromise方式

export function nextTick (cb?: Function, ctx?: Object) {
  let _resolve
  // 往全局的callbacks隊列中添加cb
  callbacks.push(() => {
    if (cb) {
      try {
        cb.call(ctx)
      } catch (e) {
        handleError(e, ctx, 'nextTick')
      }
    } else if (_resolve) {
      // 這里是支持Promise的寫法
      _resolve(ctx)
    }
  })
  if (!pending) {
    pending = true
    // 執(zhí)行timerFunc,在下一個Tick中執(zhí)行callbacks中的所有cb
    timerFunc()
  }
  // 對Promise的實現(xiàn),這也是我們使用時可以寫成nextTick.then的原因
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve
    })
  }
}
  • 深入細節(jié),理解pending有什么用,如何運作?
  • 案例1,同一輪Tick中執(zhí)行2次$nextTick,timerFunc只會被執(zhí)行一次
this.$nextTick(() => console.log('nextTick1'))
this.$nextTick(() => console.log('nextTick2'))
  • 用圖看看更直觀?

三、Vue組件的異步更新

這里如果有對Vue組件化、派發(fā)更新不是十分了解的朋友,可以先戳這里,看圖解Vue響應式原理了解下Vue組件化和派發(fā)更新的相關內(nèi)容再回來看噢~

Vue的異步更新DOM其實也是使用nextTick來實現(xiàn)的,跟我們平時使用的$nextTick其實是同一個~

這里我們回顧一下,當我們改變一個屬性值的時候會發(fā)生什么?

 根據(jù)上圖派發(fā)更新過程,我們從watcher.update開時講起,以渲染W(wǎng)atcher為例,進入到queueWatcher

1. queueWatcher做了什么?

// 用來存放Wathcer的隊列。注意,不要跟nextTick的callbacks搞混了,都是隊列,但用處不同~
const queue: Array<Watcher> = []
function queueWatcher (watcher: Watcher) {
  const id = watcher.id // 拿到Wathcer的id,這個id每個watcher都有且全局唯一
  if (has[id] == null) {
    // 避免添加重復wathcer,這也是異步渲染的優(yōu)化做法
    has[id] = true
    if (!flushing) {
      queue.push(watcher)
    }
    if (!waiting) {
      waiting = true
      // 這里把flushSchedulerQueue推進nextTick的callbacks隊列中
      nextTick(flushSchedulerQueue)
    }
  }
}

2. flushSchedulerQueue做了什么?

function flushSchedulerQueue () {
  currentFlushTimestamp = getNow()
  flushing = true
  let watcher, id
  // 排序保證先父后子執(zhí)行更新,保證userWatcher在渲染W(wǎng)atcher前
  queue.sort((a, b) => a.id - b.id)
  // 遍歷所有的需要派發(fā)更新的Watcher執(zhí)行更新
  for (index = 0; index < queue.length; index++) {
    watcher = queue[index]
    id = watcher.id
    has[id] = null
    // 真正執(zhí)行派發(fā)更新,render -> update -> patch
    watcher.run()
  }
}
  • 最后,一張圖搞懂組件的異步更新過程

四、回歸題目本身

相信經(jīng)過上文對nextTick源碼的剖析,我們已經(jīng)揭開它神秘的面紗了。這時的你一定可以堅定地把答案說出來了~話不多說,我們一起核實下,看看是不是如你所想!

如圖所示,mounted時候的innerText是“井柏然”的中文 

接下來是點擊按鈕后,打印結果如圖所示 

沒錯,輸出結果如下(意不意外?驚不驚喜?)

sync log 井柏然

nextTick1 井柏然

nextTick2 jngboran

下面簡單分析一下每個輸出:

this.$nextTick(() => console.log('nextTick1', this.$refs.name.innerText))
this.name = 'jngboran'
console.log('sync log', this.$refs.name.innerText)
this.$nextTick(() => console.log('nextTick2', this.$refs.name.innerText))

sync log:這個同步打印沒什么好說了,相信大部分童鞋的疑問點都不在這里。如果不清楚的童鞋可以先回顧一下EventLoop,這里不多贅述了~

nextTick1:注意其雖然是放在$nextTick的回調(diào)中,在下一個tick執(zhí)行,但是他的位置是在this.name = 'jngboran&#39;的前。也就是說,他的cb會比App組件的派發(fā)更新(flushSchedulerQueue)更先進入隊列,當nextTick1打印時,App組件還未派發(fā)更新,所以拿到的還是舊的DOM值。

nextTick2就不展開了,大家可以自行分析一下。相信大家對它應該是最肯定的,我們平時不就是這樣拿到更新后的DOM嗎?

最后來一張圖加深理解

寫在最后,nextTick其實在Vue中也算是比較核心的一個東西了。因為貫穿整個Vue應用的組件化、響應式的派發(fā)更新與其息息相關~深入理解nextTick的背后實現(xiàn)原理,不僅能讓你在面試的時候一展風采,更能讓你在日常開發(fā)工作中,少走彎路少踩坑!

以上就是Vue.nextTick純干貨使用方法詳解的詳細內(nèi)容,更多關于Vue.nextTick使用方法的資料請關注腳本之家其它相關文章!

相關文章

  • vue如何設置動態(tài)的柵格占位、水平偏移量、類名、樣式

    vue如何設置動態(tài)的柵格占位、水平偏移量、類名、樣式

    這篇文章主要介紹了vue如何設置動態(tài)的柵格占位、水平偏移量、類名、樣式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Vue3中element-plus全局使用Icon圖標的過程詳解

    Vue3中element-plus全局使用Icon圖標的過程詳解

    我們在用vue開發(fā)網(wǎng)站的時候,往往圖標是起著很重要的作,這篇文章主要給大家介紹了關于Vue3中element-plus全局使用Icon圖標的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-01-01
  • Vue 清除Form表單校驗信息的解決方法(清除表單驗證上次提示信息)

    Vue 清除Form表單校驗信息的解決方法(清除表單驗證上次提示信息)

    這篇文章主要介紹了Vue 清除Form表單校驗信息的解決方法(清除表單驗證上次提示信息),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • 使用vue init webpack項目名創(chuàng)建項目方式

    使用vue init webpack項目名創(chuàng)建項目方式

    這篇文章主要介紹了使用vue init webpack項目名創(chuàng)建項目方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • vue實現(xiàn)視頻全屏切換功能

    vue實現(xiàn)視頻全屏切換功能

    這篇文章主要為大家詳細介紹了如何使用vue實現(xiàn)視頻全屏切換的功能,文中的示例代碼講解詳細, 具有一定的借鑒價值,有需要的小伙伴可以參考一下
    2023-11-11
  • vue 實現(xiàn)數(shù)字滾動增加效果的實例代碼

    vue 實現(xiàn)數(shù)字滾動增加效果的實例代碼

    最近做了個項目需要做數(shù)字滾動增加的效果,剛開始接到這個項目還真是懵了,后來發(fā)現(xiàn)實現(xiàn)代碼很簡單的,下面小編給大家?guī)砹藇ue 實現(xiàn)數(shù)字滾動增加效果的實例代碼,需要的朋友參考下吧
    2018-07-07
  • Vite項目搭建與環(huán)境配置的完整版教程

    Vite項目搭建與環(huán)境配置的完整版教程

    Vite?使用?Rollup?作為默認的構建工具,可以將應用程序的源代碼打包成一個或多個優(yōu)化的靜態(tài)文件,本文就來為大家介紹一下Vite如何進行項目搭建與環(huán)境配置吧
    2023-09-09
  • Vue自定義模態(tài)對話框彈窗

    Vue自定義模態(tài)對話框彈窗

    這篇文章主要為大家詳細介紹了Vue自定義模態(tài)對話框彈窗,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Vue?Steam同款登錄驗證數(shù)字輸入框功能

    Vue?Steam同款登錄驗證數(shù)字輸入框功能

    這篇文章主要介紹了Vue?Steam同款登錄驗證數(shù)字輸入框功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-03-03
  • vue3中組件傳值的多種方法總結

    vue3中組件傳值的多種方法總結

    學習過vue2的寶子們肯定知道,組件傳值是vue項目開發(fā)過程中必不可少的功能場景,下面這篇文章主要給大家介紹了關于vue3中組件傳值的多種方法,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2023-01-01

最新評論