Vue.nextTick()
首先,我们了解一下Vue的响应式原理,当你把一个普通的 JavaScript 对象传入 Vue 实例作为data选项,Vue 将遍历此对象所有的 property,并使用Object.defineProperty把这些 property 全部转为 getter/setter。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
1、举个例子
<template>
<div>
<div ref="msgDiv">{{msg}}</div>
<div v-if="msg1">msg1的值:{{msg1}}</div>
<div v-if="msg2">msg2的值(有nextTick):{{msg2}}</div>
<div v-if="msg3">msg3的值(区别msg1):{{msg3}}</div>
<button @click=handleClick></button>
</div>
</template>
<script>
export default {
name: 'Hello',
data () {
return {
msg: '原始值',
msg1: '',
msg2: '',
msg3: ''
}
},
methods: {
handleClick () {
this.msg = '修改后的值'
this.msg1 = this.$refs.msgDiv.innerHTML
this.$nextTick(() => {
this.msg2 = this.$refs.msgDiv.innerHTML
})
this.msg3 = this.$refs.msgDiv.innerHTML
}
}
}
</script>
<style lang="scss" scoped>
</style>
点击之后的效果:

从图中可以得知:msg1和msg3显示的内容还是变换之前的,而msg2显示的内容是变换之后的。
2、this.$nextTick()的应用场景
- 在Vue生命周期的
created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。在created()钩子函数执行的时候,DOM其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。
- 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进
Vue.nextTick()的回调函数中。
3、async/await的形式
async handleClick () { this.msg = '修改后的值' this.msg1 = this.$refs.msgDiv.innerHTML await this.$nextTick() this.msg2 = this.$refs.msgDiv.innerHTML this.msg3 = this.$refs.msgDiv.innerHTML }
