Vue3源码解析--双向绑定
Vue3源码解析--双向绑定
YuXiang双向绑定是Vue 3响应式系统的核心特性之一,它通过 数据劫持 和 依赖追踪 实现了数据与视图的自动同步。
1. 双向绑定的基本概念
双向绑定是指:
- 当数据发生变化时,视图自动更新。
- 当用户操作视图时,数据自动更新。
在 Vue 中,双向绑定通常通过 v-model 指令实现。例如:
1 | <template> |
- v-model 是语法糖,它相当于 **:value=”message” @input=”message = $event.target.value”**。
- 当用户在输入框中输入内容时,message 会自动更新;当 message 变化时,输入框的内容也会自动更新。
2. 响应式系统的核心
Vue 3 的响应式系统基于 Proxy 和 依赖追踪 实现。以下是其核心概念:
2.1 Proxy
- Vue 3 使用
Proxy
对象劫持数据的读写操作。 - 当访问数据时,收集依赖(即哪些组件或计算属性依赖于该数据)。
- 当修改数据时,触发依赖更新。
2.2 依赖追踪
- 每个响应式数据都有一个依赖列表(deps),用于存储所有依赖于它的副作用(如组件的渲染函数)。
- 当数据变化时,遍历依赖列表,执行副作用。
3. 源码解析
Vue 3 的响应式系统源码位于 packages/reactivity
目录下。以下是其核心实现逻辑的解析。
3.1 响应式数据的创建
Vue 3 通过 reactive
函数将普通对象转换为响应式对象:
1 | export function reactive<T extends object>(target: T): T { |
- createReactiveObject 是创建响应式对象的核心函数。
3.1.1 createReactiveObject
1 | function createReactiveObject(target: object) { |
- Proxy 的 get 拦截器:在访问属性时调用 track,收集依赖。
- Proxy 的 set 拦截器:在修改属性时调用 trigger,触发依赖更新。
3.2 依赖收集(track)
track
函数用于收集依赖:
1 | export function track(target: object, key: unknown) { |
- targetMap:全局的 WeakMap,用于存储每个对象的依赖关系。
- depsMap:每个对象的依赖关系表,键是属性名,值是一个 Set(存储副作用)。
- activeEffect:当前正在执行的副作用(如组件的渲染函数)。
3.3 依赖触发(trigger)
trigger
函数用于触发依赖更新:
1 | export function trigger(target: object, key: unknown) { |
- 从 targetMap 中获取对象的依赖关系表。
- 从 depsMap 中获取属性的依赖列表。
- 遍历依赖列表,执行每个副作用。
3.4 副作用(effect)
副作用是指依赖于响应式数据的操作(如组件的渲染函数)。Vue 3 通过 effect
函数创建副作用:
1 | export function effect(fn: () => void) { |
- activeEffect:全局变量,用于存储当前正在执行的副作用。
- 当副作用执行时,会访问响应式数据,从而触发 track,将副作用添加到依赖列表。
3.5 v-model 的实现
v-model 是双向绑定的语法糖,其实现逻辑如下:
1 | export function withModel(props: any, emit: any) { |
- 当用户输入内容时,触发 input 事件。
- 通过 emit 触发 update:modelValue 事件,更新数据。
4. 总结
Vue 3 的双向绑定基于响应式系统实现,其核心逻辑包括:
- 响应式数据:通过
Proxy
劫持数据的读写操作。 - 依赖收集:在访问数据时,收集依赖(副作用)。
- 依赖触发:在修改数据时,触发依赖更新。
- 副作用:通过
effect
函数创建和管理副作用。
通过以上机制,Vue 3 实现了高效的双向绑定,使数据与视图能够自动同步。理解其源码实现,有助于我们更好地使用和优化 Vue 应用。