菜单

响应式系统

相关源文件

Vue.js 响应式系统是核心机制,它能在底层数据变化时自动更新 UI。本文档解释了 Vue 如何追踪数据属性的变化并在必要时触发重新渲染。有关组件系统的更多信息,请参阅组件系统;有关虚拟 DOM 渲染的详细信息,请参阅虚拟 DOM 实现

概述

Vue 的响应式系统允许声明式 UI 编程——开发者定义数据状态以及它应该如何渲染,而 Vue 会在数据变化时自动更新 DOM。这是 Vue 最显著的特性之一,也是其开发者体验的关键部分。

来源

核心原则

Vue 的响应式基于两个关键机制构建:

  1. 属性访问追踪:Vue 将数据对象的属性转换为 getter/setter,以追踪它们的访问或修改。
  2. 依赖收集:Vue 记录哪些组件依赖于哪些属性,并且只在必要时更新它们。

内部架构

来源

响应式如何建立

当 Vue 组件创建时,会通过以下过程建立响应式:

  1. 组件初始化期间会调用 initData 函数。
  2. 数据属性被观察并转换为 getter/setter。
  3. 为计算属性和用户侦听器创建 Watcher。

来源

观察者模式实现

Vue 的响应式系统基于观察者模式。我们来看看关键部分:

1. 使数据响应式化

Vue 初始化时,它会遍历数据对象,并使用 defineReactive 将每个属性转换为 getter/setter 对。

来源

2. 依赖追踪

当组件渲染时,它会访问数据属性,这会触发 getter。getter 会记录当前活动的 watcher(通常是组件的渲染 watcher)作为依赖。

来源

3. 变更通知

当数据属性发生变化时,setter 会被触发,它会通知所有依赖于此属性的 watcher。

来源

Watcher 类型

Vue 使用 Watcher 类主要用于三个目的:

Watcher 类型创建者目的
渲染 Watcher组件挂载数据变化时更新组件视图
计算属性 Watcher计算属性缓存并重新计算派生值
用户 Watcherwatch 选项/函数数据变化时执行用户回调

来源

渲染 Watcher

每个 Vue 组件在挂载过程中都会创建一个渲染 watcher。此 watcher 的 getter 函数是组件的渲染函数,它访问响应式数据并建立依赖。

来源

计算属性

计算属性创建的是惰性 watcher,它们只在其依赖发生变化时才会重新计算。

来源

组合式 API 响应式系统 (Vue 3 兼容)

Vue 2.7 包含 Vue 3 组合式 API 响应式系统的回溯版本。这提供了创建和使用响应式状态的新方式。

响应式 API

API目的
ref创建值的响应式引用
reactive创建对象的响应式代理
computed创建自动更新的计算值
watch侦听响应式源并在它们变化时运行回调
watchEffect立即运行函数并追踪依赖

来源

Effect Scope

Vue 2.7 还包含 Vue 3 的 EffectScope 概念,它有助于管理响应式副作用的生命周期。

来源

响应式工作流程

以下是响应式从初始化到更新的流程:

来源

性能考量

Vue 的响应式系统包含多项优化:

  1. 批量更新:多个属性变更只会通过异步更新队列触发一次渲染周期。
  2. 惰性 Watcher:计算属性只在被访问且“脏”时才重新计算。
  3. 属性缓存:比较值的变化以避免不必要的更新。

来源

限制和边缘情况

由于 JavaScript 的限制,Vue 的响应式系统有一些局限性:

  1. 添加/删除属性:Vue 无法检测到对象属性的添加或删除(使用 Vue.set/Vue.delete 或扩展运算符)。
  2. 数组变异:Vue 只能在使用 pushpop 等特殊方法时检测数组的变化。
  3. 嵌套对象:数组中的对象需要特殊处理才能使其响应式化。

来源

与 Vue 3 组合式 API 的集成

在 Vue 2.7 中,组合式 API 的 setup 函数与现有的响应式系统集成。

来源

结论

Vue 的响应式系统是观察者模式的强大但抽象的实现。通过透明地将数据属性转换为 getter/setter 并追踪依赖,Vue 创建了一个系统,使数据的变化能够自动反映到 UI 更新中,同时最大限度地减少了开发者的工作量。