NextTick principle in Vue
1. Why nextTick is needed
Vue adoptsAsynchronous rendering mechanism,When responsive data changes, Vue does not update the DOM immediately, but puts these changes into aqueueand inSame event loopMerge the same modifications in (Event Loop) and finally perform batch updates.
The purpose of this isImprove performance and avoid unnecessary repeated rendering。
For example:
<template> <div>{{ msg }}</div> </template> <script> export default { data() { return { msg: "Hello" }; }, mounted() { = "Vue"; (("div").innerText); // Still "Hello" this.$nextTick(() => { (("div").innerText); // It's now "Vue" }); } }; </script>
WhyOr "Hello"?
Because Vue is = "Vue"
hourDOM will not be updated immediately, but wait until this round of event loop is over before updating. Therefore, we neednextTick
to ensure that the updated DOM is obtained.
2. The principle of nextTick
Vue'snextTick
Essentially oneAsynchronous Task Scheduler, it will be in the currentExecute callback after the DOM task is completed. Its internal principles mainly depend onMicrotasks and Macrotasks。
2.1 Task Queue
Vue maintains an internalCallback queue(callback queue), whennextTick
When called, it will callback functionPush into the queue, and then wait for Vue to perform DOM updates, and then execute these callbacks in turn.
2.2 Task Scheduling Strategy
nextTick
useElegant downgradeThe strategy to choose the best asynchronous method in different environments:
- Promise(Microtask)(Preferred, supported by modern browsers)
-
MutationObserver(Microtask)(Compare
setTimeout
Faster) - setImmediate(Macrotask)(IE only supports it)
- setTimeout(Macrotask)(The final bottom-up plan)
Code implementation:
function nextTick(callback) { const p = (); (callback); }
In Vue 3:
let callbacks = []; let pending = false; function flushCallbacks() { pending = false; const copies = (0); = 0; for (let cb of copies) { cb(); } } export function nextTick(cb) { (cb); if (!pending) { pending = true; ().then(flushCallbacks); } }
Process analysis:
- Each call
nextTick(cb)
,Willcb
Put incallbacks
In queue. - if only
pending === false
, startMicrotasks ()。 - Microtask execution
flushCallbacks
, call it in turncallbacks
All callbacks in the queue.
3. The difference between nextTick in Vue 2 and Vue 3
3.1 nextTick for Vue 2
In Vue 2,nextTick
Main dependencies:
- Microtask(, MutationObserver)
- Macrotask(setImmediate, setTimeout)
- Maintained oneAsynchronous task queue, used for batch execution
nextTick
Callback.
3.2 nextTick for Vue 3
Vue 3 main optimizations:
- Use onlyPromiseAs a microtask (no longer using MutationObserver).
- More efficientAsynchronous queue processing mechanism。
Vue 3nextTick
:
const resolvedPromise = (); export function nextTick(fn) { return fn ? (fn) : resolvedPromise; }
Optimization point
- Use directly
().then(fn)
, avoiding Vue 2's complex callback queue management. - If not passed in
fn
, then returns a Promise, supportedawait this.$nextTick()
。
4. NextTick usage scenarios
4.1 Perform an action after the DOM is updated
<template> <div ref="box">{{ message }}</div> </template> <script> export default { data() { return { message: "Hello" }; }, methods: { updateMessage() { = "Vue"; this.$nextTick(() => { (this.$); // "Vue" }); } } }; </script>
4.2 Wait for DOM update in watch
watch(() => , async (newVal) => { await nextTick(); (("#counter").innerText); // Make sure the DOM is updated});
4.3 Use in Vue 3 setup
import { nextTick, ref } from "vue"; setup() { const message = ref("Hello"); const updateMessage = async () => { = "Vue"; await nextTick(); (("#msg").innerText); }; return { message, updateMessage }; }
Summarize
-
nextTick
It's one provided by VueAsynchronous task scheduling method, used to execute callbacks after DOM updates. - Vue adoptsAsynchronous batch updatemechanism,
nextTick
EnsureGet the latest DOM after data changes。 - Vue internally adoptedPromise (Microtask) priority, downgraded toMutationObserver / setTimeoutAs a backup plan.
- Vue 3 has been further optimized
nextTick
, reduces unnecessary complexity and improves performance.
You can simply understand it as:
Vue will not update the DOM immediately after modifying the data, butBatch merge modificationand on the next timeUpdate the DOM at the end of the event loop。nextTick
Let you wait until the DOM update is completed before performing the operation.
The above is personal experience. I hope you can give you a reference and I hope you can support me more.