🎬 HoRain 云小助手个人主页

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

目录

⛳️ 推荐

一、核心原理:Proxy + 依赖收集 + 副作用调度

1. 为什么用 Proxy?

二、核心实现流程(以 reactive 为例)

步骤 1:创建响应式代理

步骤 2:依赖收集(Track)

步骤 3:触发更新(Trigger)

三、关键设计:副作用函数(Effect)

1. effect 函数(核心)

2. 依赖去重与自动清理

四、与 Vue 2 的关键对比

五、ref 与 reactive 的关系

六、性能优化:调度与异步更新

1. 副作用调度(Scheduler)

2. 批量更新(Batching)

七、实际执行流程(图示)

✅ 总结:Vue 3 响应式系统优势

附:关键源码片段(简化版)


Vue 3 的响应式系统是其核心特性之一,基于 Proxy 代替了 Vue 2 的 Object.defineProperty,实现了更高效、更灵活的响应式机制。以下是其原理的深度解析,包含关键设计思想和实现逻辑:


一、核心原理:Proxy + 依赖收集 + 副作用调度

1. 为什么用 Proxy?
  • Vue 2 的缺陷
    • 无法检测对象属性的新增/删除(需 Vue.set/Vue.delete)。
    • 无法检测数组的索引修改(如 arr[0] = ...)。
    • 无法监听原始值(如 ref 需单独处理)。
  • Vue 3 的改进
    • Proxy 能拦截对象的所有操作(属性读写、in 操作、delete 等),无需额外 API。
    • 支持原始值(通过 ref 包装)和嵌套对象的响应式。

二、核心实现流程(以 reactive 为例)

步骤 1:创建响应式代理
const data = reactive({ count: 0 }) // 通过 Proxy 包装对象
  • reactive 内部
    function reactive(target) {
      return new Proxy(target, {
        get(target, key, receiver) {
          // 依赖收集(track)
          track(target, key)
          return Reflect.get(target, key, receiver)
        },
        set(target, key, value, receiver) {
          // 触发更新(trigger)
          const result = Reflect.set(target, key, value, receiver)
          trigger(target, key)
          return result
        }
      })
    }
    
步骤 2:依赖收集(Track)
  • 当读取响应式数据时(如 data.count):
    1. 触发 get 拦截器。
    2. 通过 track 将当前执行的副作用函数(如 effect)与当前数据属性count)关联。
    3. 依赖存储:使用 WeakMaptargetMapkeySet<effect>)。

关键数据结构

// 依赖存储
const targetMap = new WeakMap() // { target: map }

// 每个 target 的依赖
const keyMap = new Map() // { key: effectSet }

// 每个 key 的依赖集合
const effectSet = new Set() // { effectFn1, effectFn2 }
步骤 3:触发更新(Trigger)
  • 当修改响应式数据时(如 data.count++):
    1. 触发 set 拦截器。
    2. 通过 trigger 通知所有依赖当前 key 的副作用函数执行。
    3. 执行副作用函数(如重新渲染组件)。

三、关键设计:副作用函数(Effect)

1. effect 函数(核心)
effect(() => {
  console.log(data.count) // 依赖收集:data.count ← effect
})
  • 执行逻辑
    1. 保存当前 effect 到全局变量 activeEffect
    2. 执行传入的函数(触发 get 读取响应式数据)。
    3. 依赖收集:在 get 中将 activeEffect 添加到 targetMap
    4. 恢复 activeEffect 为上一个值。
2. 依赖去重与自动清理
  • 通过 Set 存储副作用函数,避免重复添加。
  • 依赖收集仅在 effect 执行时触发,避免冗余。

四、与 Vue 2 的关键对比

特性 Vue 2 Vue 3
核心机制 Object.defineProperty Proxy
新增/删除属性 ❌ 需 Vue.set/Vue.delete ✅ 自动支持
数组索引修改 ❌ 需 Vue.set ✅ 自动支持
原始值响应式 ❌ 需 ref ref 直接包裹原始值
依赖收集 通过 dep 数组 通过 WeakMap + Set
性能 低(需遍历对象属性) 高(仅收集实际访问的属性)

💡 示例
Vue 2 中 obj.newProp = 1 不会触发更新,Vue 3 通过 Proxyset 拦截自动触发。


五、refreactive 的关系

  • ref:包装原始值(如 number, string)为响应式对象。
    const count = ref(0) // { value: 0 }
    // 读取时自动解包:count.value
    
  • reactive:包装对象为响应式对象。
    const state = reactive({ count: 0 }) // { count: 0 }
    // 读取时直接:state.count
    
  • 内部关联ref 会调用 reactivevalue 属性包装为响应式对象。

六、性能优化:调度与异步更新

1. 副作用调度(Scheduler)
  • 默认行为:副作用函数同步执行(立即触发更新)。
  • 优化:通过 scheduler 参数异步调度(如 Vue 3 组件更新使用 nextTick)。
    effect(
      () => { /* ... */ },
      { scheduler: (job) => queueJob(job) } // 异步执行
    )
    
2. 批量更新(Batching)
  • queueJob:将多个副作用函数合并为一次执行,避免重复渲染。
    // 例如:同时修改多个响应式属性
    data.count++
    data.msg = "updated"
    // 仅触发一次更新(Vue 3 默认行为)
    

七、实际执行流程(图示)

graph LR
  A[读取响应式数据] -->|触发 get| B[track 依赖收集]
  B --> C[将 effect 添加到 targetMap]
  D[修改响应式数据] -->|触发 set| E[trigger 触发更新]
  E --> F[遍历 targetMap 中 key 的 effect 集合]
  F --> G[执行副作用函数]
  G --> H[更新视图/执行逻辑]

✅ 总结:Vue 3 响应式系统优势

  1. 全面支持:对象、数组、原始值均自动响应。
  2. 性能更高:仅收集实际访问的属性(Vue 2 需遍历所有属性)。
  3. 代码更简洁:无需 Vue.set/Vue.delete,减少开发者心智负担。
  4. 灵活性强:通过 scheduler 自定义更新策略(如异步、批量)。

💡 一句话理解
Vue 3 用 Proxy 作为“数据看门人”,在读取/修改时自动记录依赖和触发更新,实现“数据变化→自动更新视图”的闭环。


附:关键源码片段(简化版)

// 依赖收集
function track(target, key) {
  const effect = activeEffect
  if (effect) {
    let depsMap = targetMap.get(target)
    if (!depsMap) {
      depsMap = new Map()
      targetMap.set(target, depsMap)
    }
    let dep = depsMap.get(key)
    if (!dep) {
      dep = new Set()
      depsMap.set(key, dep)
    }
    dep.add(effect)
  }
}

// 触发更新
function trigger(target, key) {
  const depsMap = targetMap.get(target)
  if (depsMap) {
    const effects = depsMap.get(key)
    if (effects) {
      effects.forEach(effect => effect())
    }
  }
}

以上是 Vue 3 响应式系统的核心骨架,实际实现更复杂(如嵌套响应式、深层监听等),但原理一致。理解此机制能帮助你更高效地使用 Vue 3 的响应式 API(如 computed, watch)。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐