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

Vue NextTick介紹與使用原理

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

一、NextTick是什么

定義

在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(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本質(zhì)是一種優(yōu)化策略。

二、使用場景

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

組件內(nèi)使用vm.$nextTick() 實例方法只需要通過this. $nextTick(),并且回調(diào)函數(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新增回調(diào)函數(shù)后又執(zhí)行了timerFunc函數(shù),pending是用來標識同一個時間只能執(zhí)行一次。
export function nextTick(cb?: Function, ctx?: Object) {
  let _resolve;
  // cb 回調(diào)函數(shù)會經(jīng)統(tǒng)一處理壓入 callbacks 數(shù)組
  callbacks.push(() => {
    if (cb) {
      // 給 cb 回調(diào)函數(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 化的調(diào)用
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve;
    });
  }
}
  • timerFunc函數(shù)定義,這里是根據(jù)當前環(huán)境支持什么方法則確定調(diào)用哪個,分別有: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]()
  }
}

小結(jié):

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

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

相關(guān)文章

最新評論

任丘市| 府谷县| 英山县| 始兴县| 泰州市| 本溪| 延津县| 肥城市| 庐江县| 灵川县| 阿拉善盟| 周至县| 岳池县| 北辰区| 海丰县| 韩城市| 介休市| 海安县| 通州市| 潍坊市| 兴国县| 深圳市| 普陀区| 津南区| 略阳县| 富宁县| 遂溪县| 邵武市| 南涧| 鸡泽县| 博白县| 阜宁县| 华坪县| 绍兴市| 拉萨市| 长沙县| 黎城县| 南充市| 碌曲县| 柏乡县| 庄河市|