简说Vue3 computed原理

一. Computed 特性

  1. 延迟计算, 只有当访问到computed时才会执行computed effect。
  2. 存在数据缓存,只有当内部依赖发生变化,下次访问computed才会重新执行,否则不会重新执行
  3. 没有向 methods 一样携带参数,且需要有返回值。

二. Computed源码层解决的问题

三. Computed 的本质其实就是一个有value的对象

computed本身就是一个对象,有value属性,value有getter和setter。getter负责以来收集,setter用来派发更新,但computed大多数场景都是只是应用getter,很少应用setter。

四. Computed value getter

首先解决数据缓存的问题。 computed为了实现缓存,每一个computed都在局部范围内维护了一个变量 dirty。

  • dirty:当前数据是否为脏数据。

    • 脏数据(true):缓存结果过期,需要重新执行;首次执行getter时为true。
    • 非脏数据(false):缓存结果有效,不需要重新执行。
    • 从 不脏 变成 脏的,就是computed effect依赖的响应式变量发生改变。

这个computed effect其实就是computed回调包装一层effect函数后得到的产物。

下面是大体流程:

五. Computed effect的执行

当 computed effect函数执行的时候,会清除先前依赖的响应式变量的depset中的computed effect,这是为了防止无效的重新计算。

然后会将全局维护的 activeEffect 指向 computed effect 作为当前全局唯一激活的effect函数,然后入栈 effectStack 末尾。

之后就执行这个effect的回调,也就是computed的回调。因为computed的回调中访问了其他响应式变量,这些响应式变量的依赖收集的时候,就将当前的activeEffect,也就是当前的computed effect收集到了targetMaps对应的depset中。

然后当响应式派发更新的时候,就会用调度器去执行它depset中所有的effect函数,调度器在执行的时候会先判断effect是否有调度器,因为有一些effect函数不一定是立即执行回调的,可能是在下一轮事件循环执行,也可能是执行其他操作,而 computed effect的时候,就有调度器,调度器会让这个computed 进行 trigger,重新收集依赖,并且将 dirty 重新置为 false,意味着再次访问 computed,会重新计算 computed。

下面是调度器的代码,主要是将dirty标志位变成true,然后再去trigger:

js 复制代码
  const runner = effect(getter, { 
    // 延时执行 
    lazy: true, 
    // 标记这是一个 computed effect 用于在 trigger 阶段的优先级排序 
    computed: true, 
    // 调度执行的实现 
    scheduler: () => { 
      if (!dirty) { 
        dirty = true 
        // 派发通知,通知运行访问该计算属性的 activeEffect 
        trigger(computed, "set" /* SET */, 'value') 
      } 
    } 
  }) 

假如现在响应式变量改变,render effect依赖了computed,trigger就会将computed的depset中的render effect用调度器执行,从而再次访问computed getter,然后就会从新计算值,然后重新将render effect加入到computed的depset中。

这样就实现了computed的响应式。

相关推荐
沐言人生12 分钟前
又一个神级考公脑库-22,375篇真题终于按考点整理了
后端·面试
大包子16 分钟前
structuredClone vs lodash.cloneDeep:核心差异与选型指南
javascript·vue.js
海码事务所16 分钟前
Google Play 新个人开发者账号上架指南:12 人连续 14 天封闭测试怎么做?
前端
田威AI20 分钟前
图片内文字翻译的规格:输入输出、保真、自动化、时间与费用
前端·计算机视觉
for_ever_love__26 分钟前
MySQL 高频面试题 30 问:索引、事务、锁、日志、主从与分库分表(MySQL 8.0 版)
java·数据库·spring boot·mysql·spring cloud·面试·总结
不可能片场30 分钟前
命令行中文变问号 我用环境变量救了场
前端·electron
lerhxx39 分钟前
AI 应用中的上下文管理 —— 从"上下文窗口"到"分层压缩"的工程实践
前端·javascript
骑着蜗牛撵大象3271 小时前
多 Agent 分治协作:MapReduce 模式下的并行扇出与结果归并
前端
用户55318297321 小时前
Flutter iOS 热更新深入 Dart VM:读懂函数入口、解释执行与调用桥接
前端
前端snow1 小时前
为什么大厂要用Postgres + mogodb的框架?
前端