(Vue)Vue data 中某一个属性的值发生改变后,视图会立即同步执行重新渲染吗?

265 阅读3分钟

Vue在数据发生变化后不会立即同步执行重新渲染,而是按照一定的策略进行 DOM 的更新。我将使用一个类比来解释这个过程。

类比的解释

想象一下你是一位大厨,而Vue是你的助手。你在炒菜的时候,每次调味都会通知助手,并告诉他如何修改菜谱。在这里,你是数据变化,而助手是Vue的更新机制。

  1. 数据变化(调味过程) : 当你调味(即改变数据)时,助手(Vue)会收到通知。但他并不会立即去修改菜品(即更新 DOM),而是先记录下来需要修改的地方。
  2. 异步执行(炒菜完成后) : 为了避免频繁地去修改菜品,助手决定等你炒完一锅菜(即在下一个事件循环 tick 中)再去修改。这样可以确保只进行一次有效的修改,避免重复的工作。
  3. 更新 DOM(修改菜品) : 在下一个事件循环中,助手开始根据记录的修改点,按照预定的策略对菜品进行修改。这样就完成了数据变化后的 DOM 更新。

具体的解释

  1. 数据变化的侦听: 当数据发生变化时,Vue.js会通过其响应式系统侦听这些变化。这通常是通过 Object.defineProperty 或类似的机制来实现的。当数据发生变化时,会触发相应的 getter 和 setter,从而通知 Vue.js 相关的依赖。
  2. 队列的创建和缓冲: 一旦数据发生变化,Vue.js会创建一个队列并缓冲在同一事件循环中发生的所有数据变更。这是为了将多个数据变更合并成一个批量操作,以提高性能。这个队列通常是异步的,以确保在一个事件循环中的所有数据变更都能被捕获。
  3. Watcher的唯一推送: 如果同一个 Watcher(观察者)被多次触发,Vue.js 会确保它只被推送到队列中一次。 这是通过在推送之前检查队列中是否已经存在相同的 Watcher 来实现的,以避免重复推送。
  4. 去除重复数据的重要性: 去除重复数据对于避免不必要的计算和 DOM 操作非常重要。如果相同的数据变更被多次推送到队列中,可能会导致不必要的计算和 DOM 操作,降低性能。
  5. 事件循环中的刷新和执行: 在下一个事件循环 tick 中,Vue.js会刷新队列并执行实际的工作。这包括调用 Watcher 的更新方法,这个方法会执行实际的数据变更操作,并触发相应的视图更新。
  6. 相关源码: 相关的源码主要涉及 Vue.js 的响应式系统和更新机制。具体而言,涉及到 Watcher 类的实现,队列的创建和管理,以及数据变更时的通知机制。这些代码通常分布在 Vue.js 的源码中,主要集中在 src/core/ 目录下的文件中。

需要注意的是,Vue.js 的源码相对庞大,具体的实现细节可能有所变化,取决于 Vue.js 的版本。如果需要深入了解,建议查阅具体版本的源码文档。

总结

只要侦听到数据变化, Vue 将开启一个队列, 并缓冲在同一事件循环中发生的所有数据变更。 如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环 tick 中,Vue 刷新队列并执行实际 (已去重的)工作。

总体来说,Vue的更新机制确保了在数据变化时,不会立即执行重新渲染,而是通过异步的方式,按照一定的策略来更新 DOM,提高了性能和效率