🌟 核心概念
响应式数据:当数据变化时,依赖它的代码自动重新执行
副作用 (Effect) :需要响应数据变化的操作(如:视图渲染、计算属性)
🛠️ 核心机制
1. 依赖收集与触发
javascript
复制代码
// 三级存储结构
const targetMap = new WeakMap() // 对象级存储
→ Map() // 属性级存储
→ Set() // 副作用集合
2. 工作流程
mermaid
A[响应式对象] -->|被读取| B[track 收集依赖]
A -->|被修改| C[trigger 触发更新]
D[effect 函数] -->|执行时| E[标记 activeEffect]
B --> E
C -->|通知| D
🔑 核心 API 实现
1. reactive() - 对象响应化
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
track(target, key) // 收集依赖
return Reflect.get(...arguments)
},
set(target, key, value) {
const res = Reflect.set(...arguments)
trigger(target, key) // 触发更新
return res
}
})
}
特点:
✅ 深度响应嵌套对象
🚫 只能处理对象/数组类型
💡 适用于复杂数据结构
2. ref() - 通用响应容器
function ref(value) {
return {
_value: value,
get value() {
track(this, 'value') // 收集依赖
return this._value
},
set value(newVal) {
this._value = newVal
trigger(this, 'value') // 触发更新
}
}
}
特点:
✅ 可包装任意类型值
🔍 通过 .value 访问
💡 适合原始值或需要替换整个对象时使用
3. effect() - 副作用管理
function effect(fn) {
const _effect = () => {
activeEffect = _effect // 标记当前副作用
try { fn() } finally { activeEffect = null }
}
_effect() // 立即执行以收集依赖
return _effect
}
典型场景:
- 组件渲染
- 计算属性
- 监听器
🎯 关键设计解析
1. 依赖追踪原理
// 当访问响应式数据时
function track(target, key) {
if (!activeEffect) return
// 建立三级存储关系
let depsMap = targetMap.get(target) || targetMap.set(target, new Map()).get(target)
let dep = depsMap.get(key) || depsMap.set(key, new Set()).get(key)
dep.add(activeEffect)
}
2. 更新触发机制
// 当修改响应式数据时
function trigger(target, key) {
const depsMap = targetMap.get(target)
if (!depsMap) return
// 执行所有关联的副作用
depsMap.get(key)?.forEach(effect => effect())
}
💡 最佳实践
-
原始值用 ref
javascript 复制代码 const count = ref(0) -
对象用 reactive
const user = reactive({ name: 'Alice' }) -
组合使用
profile: reactive({ age: 25 }) }) -
避免陷阱
// ❌ 错误:直接解构会失去响应性 const { count } = reactive({ count: 0 }) // ✅ 正确:使用 toRefs const { count } = toRefs(reactiveObj)
🚀 性能优化
- 减少大对象响应化
- 合理使用 shallowRef/shallowReactive
- 及时清理无用 effect