简说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的响应式。

相关推荐
IT_陈寒10 小时前
JavaScript性能优化:5个V8引擎隐藏技巧让你的代码提速50%
前端·人工智能·后端
菠菜盼娣10 小时前
第三方插件 unplugin-icons
前端
敲代码的彭于晏10 小时前
在迁移中学习 React 18:一份来自 React 17 的升级问题清单
前端·react.js
老王熬夜敲代码11 小时前
Linux信号量
linux·笔记·面试
顾安r11 小时前
12.17 脚本工具 自动化全局跳转
linux·前端·css·golang·html
踢球的打工仔11 小时前
jquery的基本使用(2)
前端·javascript·jquery
菠菜盼娣11 小时前
Eslint 用法
vue.js
DEMO派11 小时前
前端javascript如何实现阅读位置记忆【可运行源码】
前端
苏打水com11 小时前
第十七篇:Day49-51 前端工程化进阶——从“手动”到“自动化”(对标职场“提效降本”需求)
前端·javascript·css·vue.js·html
文心快码BaiduComate11 小时前
Comate强力赋能:「趣绘像素岛」从体验泥潭到高性能可用的蜕变之路
前端·后端·程序员