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

Vue NextTick介紹與使用原理

 更新時間:2022年08月05日 10:34:04   作者:飯啊飯°  
我們對Vue中data數據的修改會導致界面對應的響應變化,而通過nextTick方法,可以在傳入nextTick的回調函數中獲取到變化后的DOM,講起來可能還是有點夢幻,下面我們直接使用nextTick體驗一下效果

一、NextTick是什么

定義

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

理解

Vue在更新DOM時時異步執(zhí)行的。當數據發(fā)生變化時,Vue將開啟一個異步更新隊列,視圖需要等隊列中所有數據變化完成之后,再統(tǒng)一進行更新。

舉例:

<body>
    <div id="app">
        <div>
            <button id="firstBtn" @click="testClick()" ref="aa">{{testMsg}}</button>
          </div>
    </div>
</body>
</html>
<script>
    new Vue({
        el:'#app',
        data () {
    return {
      testMsg:"原始值",
    }
  },
  methods:{
    testClick:function(){
      this.testMsg="修改后的值";
      console.log(this.$refs.aa.innerText);   //that.$refs.aa獲取指定DOM,輸出:原始值
      console.log(document.querySelector('#firstBtn').innerText)
    }
  }
})
</script>

這時候想獲取頁面最新的DOM節(jié)點,卻發(fā)現獲取到的仍然是舊值。

這是因為message數據在發(fā)現變化的時候,vue并不會立刻去更新Dom,而是將修改數據的操作放在了一個異步操作隊列中,如果我們一直修改相同數據,異步操作隊列還會進行去重,等待同一事件循環(huán)中的所有數據變化完成之后,會將隊列中的事件拿來進行處理,進行DOM的更新。

為什么要有nexttick

{{num}}
for(let i=0; i<100000; i++){
    num = i
}

如果沒有 nextTick 更新機制,那么 num 每次更新值都會觸發(fā)視圖更新(上面這段代碼也就是會更新10萬次視圖),有了nextTick機制,只需要更新一次,所以nextTick本質是一種優(yōu)化策略。

二、使用場景

this.testMsg="修改后的值";
console.log(this.$refs.aa.innerText);   //that.$refs.aa獲取指定DOM,輸出:原始值
Vue.nextTick(function(){
  console.log(document.querySelector('#firstBtn').innerText)
})

組件內使用vm.$nextTick() 實例方法只需要通過this. $nextTick(),并且回調函數中的 this 將自動綁定到當前的 Vue 實例上

this.message = '修改后的值'
console.log(this.$refs.aa.innerText) // => '原始的值'
this.$nextTick(function () {
    console.log(this.$refs.aa.innerText) // => '修改后的值'
})

$nextTick() 會返回一個 Promise 對象,可以是用async/await完成相同作用的事情

await Vue.nextTick()
console.log(document.querySelector('#firstBtn').innerText)

三、實現原理

  • callbacks也就是異步操作隊列
  • callbacks新增回調函數后又執(zhí)行了timerFunc函數,pending是用來標識同一個時間只能執(zhí)行一次。
export function nextTick(cb?: Function, ctx?: Object) {
  let _resolve;
  // cb 回調函數會經統(tǒng)一處理壓入 callbacks 數組
  callbacks.push(() => {
    if (cb) {
      // 給 cb 回調函數執(zhí)行加上了 try-catch 錯誤處理
      try {
        cb.call(ctx);
      } catch (e) {
        handleError(e, ctx, 'nextTick');
      }
    } else if (_resolve) {
      _resolve(ctx);
    }
  });
  // 執(zhí)行異步延遲函數 timerFunc
  if (!pending) {
    pending = true;
    timerFunc();
  }
  // 當 nextTick 沒有傳入函數參數的時候,返回一個 Promise 化的調用
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve;
    });
  }
}
  • timerFunc函數定義,這里是根據當前環(huán)境支持什么方法則確定調用哪個,分別有:Promise.then、MutationObserver、setImmediate、setTimeout;
  • 通過上面任意一種方法,進行降級操作
export let isUsingMicroTask = false
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  //判斷1:是否原生支持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]'
)) {
  //判斷2:是否原生支持MutationObserver
  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)) {
  //判斷3:是否原生支持setImmediate
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  //判斷4:上面都不行,直接用setTimeout
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}
  • 無論是微任務還是宏任務,都會放到flushCallbacks使用
  • 這里將callbacks里面的函數復制一份,同時callbacks置空
  • 依次執(zhí)行callbacks里面的函數
function flushCallbacks () {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

小結:

  • 把回調函數放入callbacks等待執(zhí)行;
  • 將執(zhí)行函數放到微任務或者宏任務中;
  • 事件循環(huán)到了微任務或者宏任務,執(zhí)行函數依次執(zhí)行callbacks中的回調。

到此這篇關于Vue NextTick介紹與使用原理的文章就介紹到這了,更多相關Vue NextTick內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Vue?日期獲取的示例代碼

    Vue?日期獲取的示例代碼

    moment.js是一款現在對時間處理的強大的函數,這篇文章主要介紹了Vue?日期獲取的示例代碼,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • vue在自定義組件上使用v-model和.sync的方法實例

    vue在自定義組件上使用v-model和.sync的方法實例

    自定義組件的v-model和.sync修飾符其實本質上都是vue的語法糖,用于實現父子組件的"數據"雙向綁定,下面這篇文章主要給大家介紹了關于vue在自定義組件上使用v-model和.sync的相關資料,需要的朋友可以參考下
    2022-07-07
  • vue.js父子組件通信動態(tài)綁定的實例

    vue.js父子組件通信動態(tài)綁定的實例

    今天小編就為大家分享一篇vue.js父子組件通信動態(tài)綁定的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • 利用Vite2和Vue3實現網站國際化的全過程

    利用Vite2和Vue3實現網站國際化的全過程

    vite2已經出來一段時間了,最近沒忍住嘗試了一下,這篇文章主要給大家介紹了關于利用Vite2和Vue3實現網站國際化的相關資料,需要的朋友可以參考下
    2021-08-08
  • vuex Module將 store 分割成模塊的操作

    vuex Module將 store 分割成模塊的操作

    這篇文章主要介紹了vuex Module將 store 分割成模塊,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • vue-router傳參的四種方式超詳細講解

    vue-router傳參的四種方式超詳細講解

    這篇文章主要介紹了vue-router傳參的四種方式超詳細,有router-link路由導航方式傳參,調用$router.push實現路由傳參,通過路由屬性name匹配路由,再根據params傳遞參數等等,結合示例代碼講解的非常詳細,需要的朋友可以參考下
    2022-12-12
  • 詳解Vue監(jiān)聽數據變化原理

    詳解Vue監(jiān)聽數據變化原理

    本篇文章主要介紹了Vue監(jiān)聽數據變化,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • Vue實現購物車基本功能

    Vue實現購物車基本功能

    這篇文章主要為大家詳細介紹了Vue實現購物車的基本功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • vue3如何監(jiān)聽頁面的滾動

    vue3如何監(jiān)聽頁面的滾動

    這篇文章主要給大家介紹了關于vue3如何監(jiān)聽頁面的滾動的相關資料,在vue中實現滾動監(jiān)聽和原生js無太大差異,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • vue3.0 proxy設置代理不成功的問題及解決方案

    vue3.0 proxy設置代理不成功的問題及解決方案

    這篇文章主要介紹了vue3.0 proxy設置代理不成功的問題及解決方案,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-12-12

最新評論