pocket-manual
pocket-manual copied to clipboard
关于 Vue nextTick
什么是 nextTick?Vue 官方给出定义:
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
单看定义比较抽象,个人理解 nextTick 主要用于在数据变化所引起的 DOM 更新完成后立即调用回调函数。说到这里可能有的人会有疑问:不是应该我修改数据之后,Vue 自动就进行相应的 DOM 更新了吗?答案是否的。
这里就要涉及到 Vue 的异步更新队列,Vue 响应式系统并不是在数据变化之后立即更新 DOM,而是按照一定策略异步执行 DOM 更新。
当监听到数据变化,Vue 开启一个队列,缓冲在同一事件循环中发生的所有数据改变(在缓冲过程中 Vue 会进行去重以避免不必要的计算和 DOM 操作)。在下一个的事件循环中,Vue 刷新队列并执行实际 (已去重的) 工作。
简单来说,在修改数据后,Vue 不会立即更新 DOM,而是等待同一事件循环中的所有数据变化完成后,再统一进行 DOM 更新。我们来看一个官方例子:
<div id="example">{{ message }}</div>
var vm = new Vue({
el: '#example',
data: {
message: '123'
}
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
Vue.nextTick(function() {
vm.$el.textContent === 'new message' // true
})
当设置 vm.message = 'new message',该组件的内容不会立即重新渲染。所以无法立即使用更新后的 DOM,即此时 vm.$el.textContent === 'new message' 的值为 false。
这时候使用 Vue.nextTick(callback) 让回调函数在数据变化所引起的 DOM 更新完成后被调用,所以此时 vm.$el.textContent === 'new message' 的值为 true。
日常开发过程中比较常见的 Vue.nextTick(callback) 应用场景:
-
在数据变化后基于新的视图执行相应的操作时需要使用,比如在输入框显示后获取该输入框的焦点。
-
如果在钩子函数
created和mounted中涉及 DOM 操作时需要使用,比如在created中获取输入框的焦点。
此外,因为 Vue.nextTick(callback) 返回一个 Promise 对象,所以可以使用 async/await 语法。基于上面提到的例子:
methods: {
async updateMessage: function () {
this.message = 'new message'
console.log(this.$el.textContent === 'new message') // false
await this.$nextTick()
console.log(this.$el.textContent === 'new message') // true
}
}
参考: