Vue3 计算属性 computed 实现原理解析

Vue3 计算属性 computed 实现原理解析

一、计算属性核心特性

Vue3 的 computed 属性是响应式系统的核心组成部分,主要实现以下特性:

  1. 延迟计算:只在需要时执行计算
  2. 缓存机制:依赖项未变化时复用计算结果
  3. 自动追踪:自动跟踪响应式依赖关系

二、实现原理拆解

2.1 基础结构

js 复制代码
计算属性的实现基于以下技术要点:
function computed(getter) {
  let value
  let dirty = true // 缓存状态标识

  const effectFn = effect(getter, {
    lazy: true,    // 延迟执行
    scheduler() {  // 调度器
      dirty = true // 触发重新计算
    }
  })

  return {
    get value() {
      if (dirty) {
        value = effectFn()
        dirty = false
      }
      return value
    }
  }
}

2.2 关键实现要素

1. 缓存控制(dirty 变量)
  • 作用:标识计算结果是否需要重新计算

  • 更新时机

    • 初始化时为 true(需要计算)
    • 依赖项变化时通过调度器重置为 true
    • 计算完成后重置为 false
2. effect 机制
  • lazy 模式:延迟执行副作用函数

  • scheduler

    • 响应依赖项变化的回调函数
    • 不直接执行计算,只标记缓存失效
js 复制代码
effect(getter, {
  lazy: true,
  scheduler() {
    if (!dirty) {
      dirty = true
      // 可添加触发更新的逻辑
    }
  }
})
3. 值计算过程
js 复制代码
get value() {
  if (dirty) {
    value = effectFn() // 执行副作用函数
    dirty = false     // 重置缓存标识
  }
  return value
}

三、核心模块协作

3.1 依赖关系建立

  1. 创建 effect 时自动收集依赖
  2. 依赖项变化触发 scheduler
  3. 调度器标记缓存失效

3.2 执行流程示例

sequenceDiagram participant User as 用户访问 participant Computed participant Effect User->>Computed: 访问.value Computed->>Computed: 检查dirty标志 alt dirty为true Computed->>Effect: 执行effectFn() Effect-->>Computed: 返回计算结果 Computed->>Computed: 更新缓存值 else Computed->>User: 直接返回缓存 end

四、与响应式系统的整合

4.1 依赖追踪实现

js 复制代码
// 简化的依赖收集示例
class Dep {
  constructor() {
    this.subscribers = new Set()
  }
  
  depend() {
    if (activeEffect) {
      this.subscribers.add(activeEffect)
    }
  }
  
  notify() {
    this.subscribers.forEach(effect => effect())
  }
}

4.2 响应式联动

当计算属性的依赖项发生变化时:

  1. 触发 setter 操作
  2. 通知关联的 effect
  3. 执行调度器函数
  4. 标记缓存失效
  5. 下次访问时重新计算

五、性能优化要点

  1. 惰性求值:避免不必要的计算
  2. 缓存复用:相同依赖返回相同结果
  3. 最小化触发:依赖变更时才标记失效
  4. 树状缓存:嵌套计算属性形成缓存链

六、完整实现示例

js 复制代码
function computed(getter) {
 let value
 let dirty = true
 let runner = effect(getter, {
   lazy: true,
   scheduler: () => {
     if (!dirty) {
       dirty = true
       // 触发组件更新等后续操作
     }
   }
 })

 return {
   get value() {
     if (dirty) {
       value = runner()
       dirty = false
     }
     return value
   }
 }
}

七、总结要点

  1. 计算属性本质是「可缓存的副作用函数」
  2. 通过 dirty 标志实现缓存有效性控制
  3. effect 的调度器机制实现依赖更新通知
  4. 值访问时才执行实际计算操作
  5. 与响应式系统深度整合实现自动依赖追踪 理解计算属性的实现原理,有助于我们在日常开发中更好地使用和优化计算属性,在复杂场景下做出合理的设计决策。
相关推荐
sunbyte几秒前
Tailwind CSS v4 主题化实践入门(自定义 Theme + 主题模式切换)✨
前端·javascript·css·tailwindcss
风之舞_yjf1 小时前
Vue基础(8)_监视属性、深度监视、监视的简写形式
javascript·vue.js·ecmascript
湛海不过深蓝1 小时前
【css】css统一设置变量
前端·css
DONSEE广东东信智能读卡器1 小时前
蓝牙身份证阅读器使用Uniapp调用二次开发demo
javascript·uni-app·蓝牙·身份证阅读器
Codingwiz_Joy1 小时前
Day28 -js开发01 -JS三个实例:文件上传 & 登录验证 & 购物商城 & ---逻辑漏洞复现 及 判断js的payload思路
开发语言·javascript·安全·安全性测试
程序员的世界你不懂1 小时前
tomcat6性能优化
前端·性能优化·firefox
爱吃巧克力的程序媛1 小时前
QML ProgressBar控件详解
前端
进取星辰2 小时前
21、魔法传送阵——React 19 文件上传优化
前端·react.js·前端框架
wqqqianqian2 小时前
国产linux系统(银河麒麟,统信uos)使用 PageOffice 在线打开Word文件,并用前端对话框实现填空填表
linux·前端·word·pageoffice
BillKu2 小时前
CSS实现图片垂直居中方法
前端·javascript·css