1. 事件循环可能是理解本篇文章的前置知识,不过也可以先看看无妨。
2. Vue 在修改数据后更新 DOM 时是异步的,这意味着,如果你在 Vue 中修改了被 watcher 依赖的数据,Vue 会开启一个任务队列,把所有修改数据的操作放入其中,【如果说同一个 watcher 依赖的数据被修改了多次,那么 Vue 只会在任务队列中放置一个 DOM 更新的任务【最后一次修改数据】,去除重复数据避免了不必要的计算】直到下一次 tick 任务被执行,DOM 才更新完毕。
3. 更简单的来说就是,比如在 Vue 生命周期中 mounted 中:我们希望对 data 中的 message 值进行修改,上代码:
<script> export default { name: "Detail", data() { return { message: 'Hello $nextTick' } }, mounted() { console.log(this.$el.textContent); this.message = 'update message'; this.$nextTick(() => { console.log(this.$el.textContent); }) } } </script>
第一次打印结果为:Hello $nextTick
第二次打印结果为:update message,
你可能会觉得这理所当然,但是如果你不使用 $nextTick 的话,结果会是两次 Hello $nextTick:
<script> export default { name: "Detail", data() { return { message: 'Hello $nextTick' } }, mounted() { console.log(this.$el.textContent); this.message = 'update message'; console.log(this.$el.textContent); } } </script>
原因就是当你修改了 message 后,DOM 不是立即更新的,它是一个异步任务,这意味着只有主线程的任务【同步任务】执行完,才会执行 DOM 更新。
4. 应用:【1】当你在 created 生命周期钩子函数中希望对 DOM 进行操作时,此时 DOM 还没被渲染,你需要使用 $nextTick() 函数。
【2】你在 mounted 中执行操作时,子组件的 DOM 可能还没有被渲染完毕,如果你在 Ajax 请求数据后把数据交给子组件使用,子组件 DOM 的更新可能会影响你在父组件 mounted 钩子函数中的操作结果,因此有必要使用一个 $nextTick() 函数。