這篇文章給大家簡單比較一下$nextTick 與 setTimeout,看看它們之間有什麼差異。
一個前端開發人員(小智)走進了一個Vue酒吧。小智點了他最喜歡的雞尾酒:Nuxt。酒保正在努力製作中。然後他自己就嘮叨了起來。
小智講述了他是如何在Vue 3的實例方法下發現$nextTick
的,並大吃一驚。小智使用Vue已經有一段時間了,他已經習慣了把$watch
和$emit
寫成實例方法。那麼,$nextTick是用來做什麼的呢? Vue文檔說,它"[defers]回調,在下一個DOM更新周期後執行"。
但是小智不相信。
他繼續講述他是如何嘗試這樣做的:
this.loadingAnimation = true this.startVeryLongCalculation() this.completeVeryLongCalculation() this.loadingAnimation = false
有用。為什麼?
nextTick
接受一個延遲到下一個DOM更新週期的回呼函數。這只是Vue的一種說法,"嘿,如果你想在DOM更新後執行一個函數(這種情況很少發生),我希望你使用nextTick
而不是setTimeout
"。
Vue.nextTick(() => {}) // syntax
下面很快就會講到setTimeout
和nextTick
參數。我們用這個範例來視覺化nextTick
的行為:
<template> <div> {{ currentTime }} </div> </template> <script> export default { name: 'getCurrentTime', data() { return { currentTime: '' } }, 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.then
或MutationObserver
來存取。"
在DOM更新後執行函數的另一種方法是使用JavaScript的setTimeout()
函數。
我們將上面的程式碼用setTimeout
取代nextTick
:
<template> <div> {{ currentTime }} </div> </template> <script> export default { name: 'getCurrentTime', data() { return { currentTime: '' } }, 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
的實作在不支援Promise
和MutationObserver
的瀏覽器(IE 6-10和Opera Mini瀏覽器)上,使用setTimeout
作為後備方法,對於不支援Promise
和MutationObserver
的瀏覽器(IE 10),它更傾向於setImmediate
。
setTimeout
時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: '', months: ['Jan', 'Feb', 'Apr', 'May', 'June', 'July', 'Aug'] } }, mounted() { this.updateScrollNextTick() }, methods: { addMessage() { if(this.month == ''){ return } this.months.push(this.month) this.month = '' this.updateScrollNextTick() }, updateScrollNextTick () { let scrolledHeight = this.$refs.scrolledHeight.clientHeight this.$nextTick(() => { this.$refs.listScroll.scrollTo({ behavior: 'smooth', top: scrolledHeight }) }) } }, }) .mount("#app") </script>
範例位址:https://codepen.io/ammezie/pen/OJpOvQE
主要部分:
運行結果:
在上面的程式碼片段中,我們想在一個新項目被添加到列表中時獲得平滑的向下滾動效果。瀏覽一下程式碼,試著修改一下,去掉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中文網其他相關文章!