Vue 3 的双向绑定是其响应式系统的直接体现,它优雅地实现了数据与视图之间的自动同步。其核心原理可以通过下面的流程图快速把握,它展示了从数据被访问到视图更新的完整闭环:

css
flowchart TD
A[访问响应式数据<br>(如模板渲染)] --> B[Proxy getter 拦截操作]
B --> C[依赖收集<br>Track]
C --> D[返回数据值]
D --> E[数据变化<br>用户输入/脚本赋值]
E --> F[Proxy setter 拦截操作]
F --> G[触发更新<br>Trigger]
G --> H[重新执行副作用<br>(如组件渲染)更新视图]
H --> A
下面我们来详细剖析图中的每个关键部分。
🔧 响应式基础:Proxy 与 Reflect
Vue 3 抛弃了 Vue 2 基于 Object.defineProperty
的实现,转而使用现代浏览器广泛支持的 Proxy
来代理目标对象。这是一个根本性的改变,带来了巨大的优势 。
- 全面的拦截能力 :
Proxy
可以拦截对一个对象的各种底层操作,包括属性读取(get
)、设置(set
)、删除(deleteProperty
)、in
操作符检查等多达13种操作。这意味着无论是对象、数组的新增、删除还是数组索引的直接设置,Vue 3 都能有效监听,无需像 Vue 2 那样重写数组方法或使用Vue.set
。 - 惰性响应化 :Vue 3 不会在初始化时递归地遍历并转换整个对象的所有嵌套属性。它采用了一种惰性策略:只有当某个嵌套属性被访问时,才会递归地将其转换为响应式。这提升了初始化的性能,特别是在处理大型复杂对象时 。
- Reflect 的配合 :在
Proxy
的处理器(handler)中,Vue 使用Reflect
对象的方法来执行默认行为。例如,在get
陷阱中,使用Reflect.get(target, key, receiver)
来获取属性值,这确保了与this
上下文相关的行为正确无误 。
⚙️ 依赖收集与触发更新
响应式系统的核心是依赖追踪,也就是明确"谁用到了这个数据",并在数据变化时通知"使用者"更新。
- 依赖收集(Track) :当组件的渲染函数(或一个
computed
计算属性、watchEffect
副作用函数)执行时,会读取响应式数据。此时,Proxy
的get
拦截器被触发。Vue 会调用track
函数,将当前正在执行的"副作用函数"(例如组件的更新函数)与该属性关联起来,记录下这个依赖关系 。这个关系被存储在一个全局的WeakMap
(targetMap) 结构中。 - 触发更新(Trigger) :当你修改响应式数据的值时(例如通过
v-model
输入或直接赋值),Proxy
的set
拦截器被触发。Vue 会调用trigger
函数,根据之前收集的依赖关系,找到所有依赖于这个属性的"副作用函数",并重新执行它们 。对于组件而言,这就意味着重新渲染,视图得以更新。
🧩 双向绑定的语法糖:v-model
在模板中,我们通过 v-model
指令来轻松实现双向绑定。在 Vue 3 中,v-model
的本质是一种语法糖,它同时做了两件事 :
- 将数据绑定到视图 :将响应式数据的值传递给表单元素的
value
(或checked
等)属性。 - 监听视图变化更新数据 :为表单元素添加一个事件监听(如
input
或change
),当用户输入时,将最新值同步回响应式数据。
在原生元素上的实现:
ini
<input v-model="message">
编译后大致等同于:
ini
<input
:value="message"
@input="message = $event.target.value"
>
在自定义组件上的实现 : Vue 3 对 v-model
进行了改进,支持多个 v-model
绑定 和自定义修饰符。
ini
<CustomInput v-model:title="pageTitle" v-model:content="pageContent" />
在子组件 CustomInput
中,需要声明对应的 props
并触发更新事件:
xml
<script setup>
defineProps(['title', 'content'])
defineEmits(['update:title', 'update:content'])
</script>
<!-- 在模板中触发 -->
<input
:value="title"
@input="$emit('update:title', $event.target.value)"
>
💎 总结:Vue 3 的卓越之处
Vue 3 的双向绑定原理建立在其先进的响应式系统之上。通过 Proxy
实现全面、精确的数据劫持,结合高效的依赖收集和触发更新机制,最终通过 v-model
指令提供简洁的模板语法。这套设计使得 Vue 3 在性能、功能性和开发体验上相比 Vue 2 都有了显著的提升 。 希望这些解释能帮助你透彻地理解 Vue 3 双向绑定的工作原理。