Vue深入理解响应式原理之$nextTick()

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() 函数。

上一篇:CIO应该了解的归档基本要素


下一篇:error: /proc must be mounted