Home >Web Front-end >Front-end Q&A >Does vue refresh dom in real time?
vue does not refresh the dom in real time. Data updates in Vue are asynchronous, which means that the modified DOM elements cannot be obtained immediately after modifying the Data. Vue executes asynchronously when updating the DOM. As long as it detects data changes, Vue will open a queue and buffer all data changes that occur in the same event loop. If the same watcher is triggered multiple times, it will only be pushed. Once in the queue, this deduplication during buffering is very important to avoid unnecessary calculations and DOM operations.
The operating environment of this tutorial: windows7 system, vue3 version, DELL G3 computer.
Data updates in Vue are asynchronous, which means that we cannot obtain the modified DOM elements immediately after modifying the Data.
Vue executes asynchronously when updating DOM
. As long as it detects data changes, Vue
will open a queue and buffer it in All data changes that occur in the same event loop will only be pushed into the queue once if the same watcher
is triggered multiple times. This removal of duplicate data during buffering is helpful to avoid unnecessary calculations and DOM
The operation is very important, then, in the next event loop tick
, Vue
flushes the queue and performs the actual (deduplicated) work,Vue
Internally attempts to use native Promise.then
, MutationObserver
and setImmediate
for asynchronous queues. If the execution environment does not support it, it will be used setTimeout(fn, 0)
instead.
The principle of Vue asynchronously updating DOM
1. When can I get the real DOM element?
In Vue's nextTick callback.
2. Why does Vue need to use the nextTick method to obtain the latest DOM?
When vue calls Watcher to update the view, it does not update it directly. Instead, it adds the Watcher that needs to be updated to the queueWatcher queue, and then passes the specific update method flushSchedulerQueue to nexTick for calling.
// src > core > observer > watcher.js + scheduler.js// 当一个 Data 更新时,会依次执行以下代码
// 1. 触发 Data.set
// 2. 调用 dep.notify
// 3. Dep 会遍历所有相关的 Watcher 执行 update 方法
class Watcher {
// 4. 执行更新操作
update() {
queueWatcher(this);
}
}
const queue = [];
function queueWatcher(watcher: Watcher) {
// 5. 将当前 Watcher 添加到异步队列
queue.push(watcher);
// 6. 执行异步队列,并传入回调
nextTick(flushSchedulerQueue);
}
// 更新视图的具体方法
function flushSchedulerQueue() {
let watcher, id;
// 排序,先渲染父节点,再渲染子节点
// 这样可以避免不必要的子节点渲染,如:父节点中 v-if 为 false 的子节点,就不用渲染了
queue.sort((a, b) => a.id - b.id);
// 遍历所有 Watcher 进行批量更新。
for (index = 0; index
2.2 nextTick -- Add the incoming flushSchedulerQueue to the callbacks array, and then execute the timerFunc method.
const callbacks = [];
let timerFunc;
function nextTick(cb?: Function, ctx?: Object) {
let _resolve;
// 1.将传入的 flushSchedulerQueue 方法添加到回调数组
callbacks.push(() => {
cb.call(ctx);
});
// 2.执行异步任务
// 此方法会根据浏览器兼容性,选用不同的异步策略
timerFunc();
}
2.3 timerFunc method -- is an asynchronous method created based on browser compatibility. After executing this method, the flushSchedulerQueue method will be called for specific DOM updates.
let timerFunc;
// 判断是否兼容 Promise
if (typeof Promise !== "undefined") {
timerFunc = () => {
Promise.resolve().then(flushCallbacks);
};
// 判断是否兼容 MutationObserver
// https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver
} else if (typeof MutationObserver !== "undefined") {
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);
};
// 判断是否兼容 setImmediate
// 该方法存在一些 IE 浏览器中
} else if (typeof setImmediate !== "undefined") {
// 这是一个宏任务,但相比 setTimeout 要更好
timerFunc = () => {
setImmediate(flushCallbacks);
};
} else {
// 如果以上方法都不知道,使用 setTimeout 0
timerFunc = () => {
setTimeout(flushCallbacks, 0);
};
}
// 异步执行完后,执行所有的回调方法,也就是执行 flushSchedulerQueue
function flushCallbacks() {
for (let i = 0; i
2.4 Improve logical judgment
2.4.1 Judge the has identifier to avoid adding the same Watcher to a Queue;
2.4.2 Determine the waiting flag to allow all Watchers to be updated in one tick;
2.4.3 Determine the flushing flag to process new Watchers that may be generated when Watchers are rendered.
If the v-if condition is triggered, the new Watcher will render.
tip: nextTick is just an asynchronous task simply simulated through Promise, setTimeout and other methods.
3. Why can this.$nextTick obtain the updated DOM?
Calling this.$nextTick is actually calling the nextTick method in the figure and executing the callback function in the asynchronous queue. According to the first-in-first-out principle, the update asynchronous queue triggered by modifying Data will be executed first. After the execution is completed, a new DOM will be generated. Next, when the callback function of this.$nextTick is executed, the updated DOM element can be obtained.
// 我们使用 this.$nextTick 其实就是调用 nextTick 方法
Vue.prototype.$nextTick = function (fn: Function) {
return nextTick(fn, this);
};
Summary: The principle of vue asynchronous update
When you modify the Data in Vue, all and The Watcher related to this Data is updated.
First, all Watchers will be added to the Queue.
Then, call the nextTick method to perform the asynchronous task.
In the callback of the asynchronous task, sort the Watchers in the Queue, and then perform the corresponding DOM update.
(Learning video sharing: vuejs introductory tutorial, Basic programming video)
The above is the detailed content of Does vue refresh dom in real time?. For more information, please follow other related articles on the PHP Chinese website!