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

Vue NextTick介紹與使用原理

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

一、NextTick是什么

定義

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

理解

Vue在更新DOM時時異步執(zhí)行的。當數(shù)據(jù)發(fā)生變化時,Vue將開啟一個異步更新隊列,視圖需要等隊列中所有數(shù)據(jù)變化完成之后,再統(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ā)現(xiàn)獲取到的仍然是舊值。

這是因為message數(shù)據(jù)在發(fā)現(xiàn)變化的時候,vue并不會立刻去更新Dom,而是將修改數(shù)據(jù)的操作放在了一個異步操作隊列中,如果我們一直修改相同數(shù)據(jù),異步操作隊列還會進行去重,等待同一事件循環(huán)中的所有數(shù)據(jù)變化完成之后,會將隊列中的事件拿來進行處理,進行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(),并且回調函數(shù)中的 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)

三、實現(xiàn)原理

  • callbacks也就是異步操作隊列
  • callbacks新增回調函數(shù)后又執(zhí)行了timerFunc函數(shù),pending是用來標識同一個時間只能執(zhí)行一次。
export function nextTick(cb?: Function, ctx?: Object) {
  let _resolve;
  // cb 回調函數(shù)會經(jīng)統(tǒng)一處理壓入 callbacks 數(shù)組
  callbacks.push(() => {
    if (cb) {
      // 給 cb 回調函數(shù)執(zhí)行加上了 try-catch 錯誤處理
      try {
        cb.call(ctx);
      } catch (e) {
        handleError(e, ctx, 'nextTick');
      }
    } else if (_resolve) {
      _resolve(ctx);
    }
  });
  // 執(zhí)行異步延遲函數(shù) timerFunc
  if (!pending) {
    pending = true;
    timerFunc();
  }
  // 當 nextTick 沒有傳入函數(shù)參數(shù)的時候,返回一個 Promise 化的調用
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve;
    });
  }
}
  • timerFunc函數(shù)定義,這里是根據(jù)當前環(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里面的函數(shù)復制一份,同時callbacks置空
  • 依次執(zhí)行callbacks里面的函數(shù)
function flushCallbacks () {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

小結:

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

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

相關文章

最新評論

南安市| 自治县| 陇西县| 新巴尔虎左旗| 巴楚县| 万载县| 漯河市| 三穗县| 临漳县| 格尔木市| 太原市| 吉安县| 于田县| 肃北| 林口县| 洱源县| 都匀市| 杂多县| 精河县| 高密市| 崇阳县| 尚志市| 从江县| 甘泉县| 清丰县| 盐池县| 从化市| 搜索| 武夷山市| 广河县| 台东市| 吉木乃县| 昂仁县| 泰安市| 乡城县| 富蕴县| 新建县| 夏河县| 稷山县| 外汇| 凌海市|