1032 字
5 分钟
Vue3 响应式系统

题目描述#

实现 Vue3 响应式系统核心功能:

  1. reactive() 创建深层响应式对象
  2. effect() 注册副作用函数并自动追踪依赖
  3. 依赖自动收集和触发更新机制
  4. 处理嵌套 effect 场景
  5. 支持分支切换优化 要求实现响应式数据劫持、依赖收集、触发更新等核心机制。

解题思路#

  1. 代理拦截:使用 Proxy 拦截对象 get/set 操作
  2. 依赖管理:建立 WeakMap→Map→Set 三级依赖存储结构
  3. 副作用函数:effect 封装回调并自动追踪依赖
  4. 嵌套处理:使用栈结构管理嵌套 effect
  5. 依赖清理:每次执行前清除旧依赖,避免无效更新

关键洞察#

  1. 精准依赖追踪:三级映射结构确保属性级依赖收集
  2. 异步更新优化:微任务队列合并多次更新
  3. 内存安全管理:WeakMap 自动释放无引用对象
  4. 嵌套场景处理:effect 栈保持当前执行上下文
  5. 分支切换优化:清理旧依赖解决条件分支问题

代码流程#

flowchart TD
    A[reactive创建响应式对象] -->|Proxy代理| B
    subgraph 依赖收集
    B[对象属性访问] --> C[track收集当前effect]
    end
    subgraph 触发更新
    D[对象属性修改] --> E[trigger通知相关effects]
    end
    F[effect注册] --> G[初始化执行]
    G --> H[建立依赖关系]
    E -->|调度| I[执行effect]

代码实现#

// 存储副作用函数的桶
const bucket = new WeakMap()
// 当前激活的effect
let activeEffect = null
// effect调用栈
const effectStack = []
// 创建响应式对象
function reactive(target) {
return new Proxy(target, {
get(target, key, receiver) {
track(target, key) return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
const oldValue = target[key] const result = Reflect.set(target, key, value, receiver)
// 值变化时才触发更新
if (oldValue !== value) {
trigger(target, key)
}
return result
}
})
}
// 追踪依赖
function track(target, key) {
if (!activeEffect) return
// 获取对象的依赖映射
let depsMap = bucket.get(target) if (!depsMap) {
bucket.set(target, (depsMap = new Map()))
}
// 获取属性的依赖集合
let deps = depsMap.get(key) if (!deps) {
depsMap.set(key, (deps = new Set()))
}
// 将当前effect添加到依赖集合
deps.add(activeEffect)
// 将依赖集合添加到effect的deps中(用于清理)
activeEffect.deps.push(deps)
}
// 触发更新
function trigger(target, key) {
const depsMap = bucket.get(target) if (!depsMap) return
const effects = depsMap.get(key) if (!effects) return
// 创建新Set避免无限循环
const effectsToRun = new Set() effects.forEach(effectFn = >{
if (effectFn !== activeEffect) {
effectsToRun.add(effectFn)
}
})
// 异步执行更新
queueMicrotask(() = >{
effectsToRun.forEach(effectFn = >{
effectFn()
})
})
}
// 副作用函数
function effect(fn) {
const effectFn = () = >{
// 清理旧依赖
cleanup(effectFn)
// 设置当前激活的effect
activeEffect = effectFn effectStack.push(effectFn)
// 执行副作用函数
fn()
// 恢复之前的effect
effectStack.pop() activeEffect = effectStack[effectStack.length - 1]
}
// 存储依赖集合
effectFn.deps = []
// 立即执行
effectFn()
return effectFn
}
// 清理依赖
function cleanup(effectFn) {
for (const dep of effectFn.deps) {
dep.delete(effectFn)
}
effectFn.deps.length = 0
}

使用示例#

// 创建响应式对象
const obj = reactive({
count: 0,
text: 'hello'
})
// 注册副作用函数
effect(() = >{
console.log(`Count: $ {
obj.count
}`)
})
// 嵌套effect示例
effect(() = >{
console.log('Outer effect')
effect(() = >{
console.log(`Inner effect: $ {
obj.text
}`)
})
})
// 分支切换示例
effect(() = >{
console.log(obj.count > 0 ? obj.text: 'count is zero')
})
// 测试响应式更新
obj.count++ // 触发更新
obj.text = 'world' // 触发更新
// 输出结果:
// Count: 0
// Outer effect
// Inner effect: hello
// count is zero
//
// Count: 1
// Inner effect: world
// world

业务场景#

  1. 组件状态管理:驱动Vue组件数据响应式更新
  2. 自动DOM更新:数据变化触发视图重新渲染
  3. 状态监听:实现watch/watchEffect基础能力
  4. 数据绑定:表单输入与状态自动同步
  5. 派生状态:基于其他状态自动计算新值

相似题目#

  1. 实现 ref 响应式引用(中等) 核心:对象包装 + value属性拦截
  2. 实现 computed 计算属性(中等) 核心:懒计算 + 结果缓存
  3. 实现 Vue2 响应式系统(中等) 核心:Object.defineProperty + 递归劫持
  4. 实现观察者模式(简单) 核心:Subject/Observer 接口
  5. 实现 Promise A+规范(困难) 核心:状态机 + 异步回调管理
Vue3 响应式系统
https://website-truelovings-projects.vercel.app/posts/code/vue/vue3-响应式系统/
作者
欢迎来到StarSky的网站!
发布于
2025-08-13
许可协议
CC BY-NC-SA 4.0