Vue nextTick 的正确姿势是什么?是时候该掌握 nextTick 了!
2023-09-21 20:36:38
我们日常开发中,通常会使用 Vue 的 nextTick 方法在 DOM 更新后运行函数。我们通常认为 nextTick 的原理是:在当前任务结束后,DOM 更新完毕后,异步队列清空时执行(即代码执行完毕之后执行)。
因此,有以下代码:
vm.$nextTick(() => {
console.log('DOM 更新完毕');
});
console.log('执行完毕');
我们猜测会依次打印:1、2、3。但是实际效果中,只会输出一次:3。为什么会出现这样的情况?我们来一探究竟。
Vue 中的数据更新机制
我们在 Vue 中初始化一个变量 msg 为 0,我们定义 watch 监听 msg,实际上会被 Vue 这样调用 vm.$watch(keyOrFn, handler, options)
。$watch
是我们初始化的时候调用的,这样会执行 handler
函数。
// Vue 实例初始化时执行
const vm = new Vue({
data() {
return {
msg: 0
};
},
watch: {
msg(newValue, oldValue) {
// msg 发生变化时触发
console.log(`监听到 msg 的变化,现在 msg 为:${newValue}`);
}
}
});
// 开始手动更新 msg 的值
vm.msg = 1;
实际上,vm.msg
的值并不会立刻更新,而是变为一个任务先放入消息队列中,然后在执行栈清空后,这个任务会被执行,然后更新 msg
的值。此时,我们的 watch 函数被调用,在监听到值变化的时候,我们在 watch
中执行了一个 vm.$nextTick
,然后将函数放入消息队列中。
在本次任务执行完毕后,所有进入消息队列的任务都会依次执行,其中包括:vm.msg
的值更新、vm.$nextTick
函数的执行。但是 vm.$nextTick
的执行实际上是在 msg
的值更新之后,所以 watch 函数会被再次调用,所以 console.log
输出 3。
这就是 为什么我们看到的输出只有 3 的原因。因为 msg
的值更新和 vm.$nextTick
函数都是异步的,而 console.log('执行完毕');
是同步执行的,所以 console.log('执行完毕');
就会先执行。
如何正确使用 nextTick?
1. 用于 DOM 更新后操作
在需要在 DOM 更新完毕后执行操作时,可以使用 nextTick
。例如,在以下场景中,可以使用 nextTick
:
- 需要在 DOM 元素被渲染后获取其尺寸;
- 需要在 DOM 元素被渲染后执行动画;
- 需要在 DOM 元素被渲染后执行表单验证。
2. 确保回调函数在组件更新完毕后执行
在组件更新完毕后执行回调函数时,可以使用 nextTick
。例如,在以下场景中,可以使用 nextTick
:
- 需要在组件更新完毕后获取组件的最新数据;
- 需要在组件更新完毕后执行组件的某个方法;
- 需要在组件更新完毕后执行组件的某个生命周期钩子函数。
3. 避免无限循环
如果在 nextTick
的回调函数中再次调用 nextTick
,可能会导致无限循环。因此,在使用 nextTick
时,应避免在回调函数中再次调用 nextTick
。
4. 避免在销毁的组件中使用 nextTick
在销毁的组件中使用 nextTick
可能会导致错误。因此,在销毁组件之前,应确保不再使用 nextTick
。
总结
nextTick
是一种异步方法,可以在 DOM 更新完毕后执行函数。在需要在 DOM 更新完毕后执行操作时,可以使用 nextTick
。但是,在使用 nextTick
时,应注意避免无限循环和在销毁的组件中使用 nextTick
。