vue3的响应式设计原理
Vue 3 的响应式设计是其核心特性之一,依赖于 Proxy 和 依赖收集机制,相比 Vue 2 的 Object.defineProperty
,Vue 3 的响应式系统更加高效、灵活且易于维护。
以下是 Vue 3 响应式设计的核心原理:
一、核心机制概览
-
使用 Proxy 实现响应式
-
Vue 3 用
Proxy
包装对象,实现对属性的读取和设置的拦截(get
和set
)。 -
相比 Vue 2,
Proxy
可以监听新增属性和删除属性,避免 Vue 2 的Vue.set
限制。
-
-
依赖收集(Dep)与触发更新(Trigger)
-
Vue 会在
getter
中收集当前运行的副作用函数(例如组件的渲染函数)。 -
当数据发生变化时,
setter
会触发这些副作用函数,重新执行。
-
-
响应式核心工具函数
-
reactive()
:将对象转换为响应式对象。 -
ref()
:将基本类型(如number
、string
)或对象封装成响应式引用。 -
computed()
:计算属性,具备缓存能力。 -
effect()
(Vue 内部 API):注册副作用函数,用于响应式依赖追踪。
-
二、基本流程图
-
调用
reactive(obj)
-> 返回 Proxy 包装对象 -
首次访问属性
proxy.a
-> 执行get
,收集依赖 -
修改属性
proxy.a = 2
-> 执行set
,触发依赖更新
三、依赖追踪与触发的简化示意
// 模拟一个简单响应式系统
let targetMap = new WeakMap();function track(target, key) {const effect = activeEffect;if (!effect) return;let depsMap = targetMap.get(target);if (!depsMap) {depsMap = new Map();targetMap.set(target, depsMap);}let deps = depsMap.get(key);if (!deps) {deps = new Set();depsMap.set(key, deps);}deps.add(effect);
}function trigger(target, key) {const depsMap = targetMap.get(target);if (!depsMap) return;const deps = depsMap.get(key);deps && deps.forEach(effect => effect());
}let activeEffect = null;
function effect(fn) {activeEffect = fn;fn(); // 执行函数,会触发 get,从而 trackactiveEffect = null;
}function reactive(obj) {return new Proxy(obj, {get(target, key, receiver) {track(target, key);return Reflect.get(target, key, receiver);},set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver);trigger(target, key);return result;}});
}
四、Vue 3 中响应式的优势
特性 | Vue 2 | Vue 3 |
---|---|---|
基础实现 | Object.defineProperty | Proxy |
新增/删除属性 | 需要手动使用 Vue.set | 原生支持 |
性能 | 多层嵌套对象递归劫持,性能差 | 延迟代理,性能好 |
API 风格 | Options API 为主 | 支持 Composition API |
五、实战示例
import { reactive, effect } from 'vue'const state = reactive({ count: 0 })effect(() => {console.log(`count is: ${state.count}`) // 自动收集依赖
})state.count++ // 自动触发更新
如果你需要可视化原理图,我可以为你画一个响应式原理的流程图,要我帮你画一个吗?