pocket-manual icon indicating copy to clipboard operation
pocket-manual copied to clipboard

关于 Vue nextTick

Open FishPlusOrange opened this issue 7 years ago • 0 comments

什么是 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) 应用场景:

  1. 在数据变化后基于新的视图执行相应的操作时需要使用,比如在输入框显示后获取该输入框的焦点。

  2. 如果在钩子函数 createdmounted 中涉及 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
  }
}

参考:

FishPlusOrange avatar Aug 28 '18 12:08 FishPlusOrange