简介:vue的nextTick底层执行过程和作用
Vue 作为目前最为主流的前端 MVVM 框架之一,在熟练使用的基础上,去深入理解其实现原理是非常有意义的一件事情。
可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 Watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
下面是 $nextTick 方法的大致执行过程
通过这样的异步处理方式,Vue 在下次 DOM 更新循环结束后执行 $nextTick 的回调函数,确保在回调函数内部能够获取到最新的 DOM 数据。
注意:Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
使用 $nextTick 的常见场景是在更新数据后,立即获取更新后的 DOM 元素的状态,例如计算 DOM 元素的尺寸或位置。另一个常见用例是在修改数据后,执行某些依赖于更新后的数据的操作,确保在 DOM 更新完成后执行这些操作。
<template>
<div>
<p>计数:{{ count }}</p>
<button @click="increment">增加计数</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0,
};
},
methods: {
increment() {
this.count++;
// 在下次 DOM 更新循环结束后执行回调函数
this.$nextTick(() => {
// DOM 已更新,可以执行额外操作
this.logElementSize();
});
},
logElementSize() {
// 获取元素尺寸
const element = this.$el.querySelector('p');
const { width, height } = element.getBoundingClientRect();
console.log('元素宽度:', width, '元素高度:', height);
},
},
};
</script>
在vue2中$nextTick是一个全局函数,可以直接通过 this.$nextTickcallback() 调用。具体使用如下:
this.$nextTick(() => {
// 在 DOM 更新后执行的回调函数
});
在vue3中$nextTick不再作为VUE实例的方法,而是一个独立的函数,需要使用时导入。此外nextTick返回的是一个Promise对象。因此,我们不仅可以通过传入函数处理回调,还可以通过 .then() 来处理回调:
// Vue 3 中的 nextTick
import { nextTick } from 'vue';
nextTick(()=>{
// 在 DOM 更新后执行的回调函数
})
nextTick().then(() => {
// 在 DOM 更新后执行的回调函数
});
// 或使用异步函数和 await
async function someFunction() {
// ...修改数据
await nextTick();
// 在 DOM 更新后执行的回调函数
}
总结:
Vue 3 中的 $nextTick 与 Vue 2 中的 $nextTick 在功能上基本一致,都用于在下次 DOM 更新循环结束后执行回调函数。然而,Vue 3 中的 $nextTick 被作为一个独立的函数导入,并返回一个 Promise 对象,而不再作为 Vue 实例的方法。这样的改变使得代码更加清晰,并且能够更好地与现代 JavaScript 中的 Promise 和异步函数结合使用。
有遗漏或者不对的可以在我的公众号留言哦