首頁  >  文章  >  web前端  >  $nextTick VS setTimeout,看看它們的差異

$nextTick VS setTimeout,看看它們的差異

青灯夜游
青灯夜游轉載
2021-07-14 18:21:302272瀏覽

這篇文章給大家簡單比較一下$nextTick 與 setTimeout,看看它們之間有什麼差異。

$nextTick VS setTimeout,看看它們的差異

一個前端開發人員(小智)走進了一個Vue酒吧。小智點了他最喜歡的雞尾酒:Nuxt。酒保正在努力製作中。然後他自己就嘮叨了起來。

小智講述了他是如何在Vue 3的實例方法下發現$nextTick的,並大吃一驚。小智使用Vue已經有一段時間了,他已經習慣了把$watch$emit寫成實例方法。那麼,$nextTick是用來做什麼的呢? Vue文檔說,它"[defers]回調,在下一個DOM更新周期後執行"。

但是小智不相信。

他繼續講述他是如何嘗試這樣做的:

this.loadingAnimation = true
this.startVeryLongCalculation()
this.completeVeryLongCalculation()
this.loadingAnimation = false

有用。為什麼?

nextTick做什麼?

nextTick接受一個延遲到下一個DOM更新週期的回呼函數。這只是Vue的一種說法,"嘿,如果你想在DOM更新後執行一個函數(這種情況很少發生),我希望你使用nextTick而不是setTimeout "。

Vue.nextTick(() => {}) // syntax

下面很快就會講到setTimeoutnextTick參數。我們用這個範例來視覺化nextTick的行為:

<template>
  <div>
    {{ currentTime }}
  </div>
</template>

<script>
export default {
  name: &#39;getCurrentTime&#39;,
  data() {
    return {
      currentTime: &#39;&#39;
    }
  },
  mounted() {
    this.currentTime = 3;

    this.$nextTick(() => {
        let date = new Date()
        this.currentTime = date.getFullYear()
    });
  }
}
</script>

在J電腦上執行這個程式碼片段。它將顯示2021年。並不是說如果你去掉nextTick,就不會得到同樣的結果。然而,你應該明白,Vue會根據資料中的內容對DOM進行修改。

在上面的程式碼片段中,Vue將DOM更新為3,然後呼叫回調,將DOM更新為2021,最後將控制權交給瀏覽器,瀏覽器將顯示2021

到目前為止,我們已經研究了nextTick在回呼隊列中插入回呼函數並在適當的時候執行該函數。

這個你可能會感興趣,nextTick中的回呼是作為事件循環中的一個微任務使用的。 nextTick原始程式碼明確指出,"nextTick行為利用了微任務佇列,可以透過本地的Promise.thenMutationObserver來存取。"

setTimeout vs nextTick

在DOM更新後執行函數的另一種方法是使用JavaScript的setTimeout()函數。

我們將上面的程式碼用setTimeout取代nextTick:

<template>
  <div>
    {{ currentTime }}
  </div>
</template>

<script>
export default {
  name: &#39;getCurrentTime&#39;,
  data() {
    return {
      currentTime: &#39;&#39;
    }
  },
  mounted() {
    this.currentTime = 3;

    setTimeout(() => {
      let date = new Date()
      this.currentTime = date.getFullYear()
    }, 0);
  }
}
</script>

執行此程式碼片段。首先看到3然後2021。它發生得很快,因此如果沒有看到此行為,則需要刷新瀏覽器。

在上面的程式碼片段中,Vue將DOM更新為3,並提供瀏覽器控制。然後瀏覽器顯示3,呼叫回呼函數,將DOM更新到2021,最後將控制權交給瀏覽器,現在瀏覽器顯示2021

nextTick的實作在不支援PromiseMutationObserver的瀏覽器(IE 6-10和Opera Mini瀏覽器)上,使用setTimeout作為後備方法,對於不支援PromiseMutationObserver的瀏覽器(IE 10),它更傾向於setImmediate

何時使用nexttick

  • 當你想要使用setTimeout
  • #當你想確定DOM能反映你的資料時
  • 在嘗試執行非同步操作時,遇到Uncaught (in promise) DOMException等錯誤。記住,Vue是非同步更新DOM的

最後來個範例:

<div id="app">
  <div ref="listScroll" class="scrolledList">
    <ul ref="scrolledHeight">
      <li v-for="month in months">
        {{month}}
      </li>               
    </ul>
  </div>

  <input type="text" placeholder="Add Month" v-model="month">
  <button @click="addMessage" @keyup.enter="addMessage"> Add Month</button>
</div>

<script src="https://unpkg.com/vue@next"> 
  Vue.createApp({
    data() {
      return {
        month: &#39;&#39;,
        months: [&#39;Jan&#39;, &#39;Feb&#39;, &#39;Apr&#39;, &#39;May&#39;, &#39;June&#39;, &#39;July&#39;, &#39;Aug&#39;]
      }
    },
    mounted() {
      this.updateScrollNextTick()
    },
    methods: {
      addMessage() {
        if(this.month == &#39;&#39;){
          return
        }

        this.months.push(this.month)
        this.month = &#39;&#39;
        this.updateScrollNextTick()
      },
      updateScrollNextTick () {
        let scrolledHeight = this.$refs.scrolledHeight.clientHeight

        this.$nextTick(() => {
          this.$refs.listScroll.scrollTo({
            behavior: &#39;smooth&#39;,
            top: scrolledHeight
          })
        })
      }
    },
  })
  .mount("#app")
</script>

範例位址:https://codepen.io/ammezie/pen/OJpOvQE

主要部分:

$nextTick VS setTimeout,看看它們的差異

運行結果:

$nextTick VS setTimeout,看看它們的差異

在上面的程式碼片段中,我們想在一個新項目被添加到列表中時獲得平滑的向下滾動效果。瀏覽一下程式碼,試著修改一下,去掉nextTick,你就會失去那種平滑的滾動效果。你也可以試著用setTimeout來取代nextTick

總結

在本文中,我們探討了nextTick是如何運作的。我們進一步了解了它與普通的JavaScript setTimeout的不同之處,並介紹了實際的用例。

英文原文網址:https://blog.logrocket.com/understanding-nexttick-in-vue-js/

作者:Chimezie Enyinnaya

#譯者:前端小智

轉載網址:https://segmentfault.com/a/1190000040246186

更多程式相關知識,請造訪:程式設計入門! !

以上是$nextTick VS setTimeout,看看它們的差異的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除