当前位置: 首页 > news >正文

Vue 3.0中响应式依赖和更新

响应式依赖和更新是Vue 3.0中最重要的机制,其核心代码如下,本文将结合代码对这个设计机制作出一些解释。

// 全局依赖存储:WeakMap<target, Map<key, Set<effect>>>
const targetMap = new WeakMap();// 当前活动的副作用函数(如组件的渲染函数)
let activeEffect = null;// 响应式入口函数
function reactive(target) {return createReactiveObject(target, mutableHandlers);
}// 创建响应式代理对象
function createReactiveObject(target, handlers) {if (typeof target !== 'object' || target === null) {return target; // 非对象直接返回}return new Proxy(target, handlers);
}// Proxy 拦截器配置
const mutableHandlers = {get(target, key, receiver) {track(target, key); // 依赖收集const res = Reflect.get(target, key, receiver);if (typeof res === 'object' && res !== null) {return reactive(res); // 深度响应式}return res;},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;},// 其他拦截器(deleteProperty/has/ownKeys 等省略)
};// 依赖收集:建立 target.key → effect 的映射
function track(target, key) {if (!activeEffect) return; // 无活动 effect 则退出let depsMap = targetMap.get(target);if (!depsMap) {targetMap.set(target, (depsMap = new Map()));}let dep = depsMap.get(key);if (!dep) {depsMap.set(key, (dep = new Set()));}if (!dep.has(activeEffect)) {dep.add(activeEffect); // 添加 effect 到依赖集合activeEffect.deps.push(dep); // 反向关联(用于清理)}
}// 触发更新:执行 target.key 的所有依赖 effect
function trigger(target, key) {const depsMap = targetMap.get(target);if (!depsMap) return;const effects = new Set();const dep = depsMap.get(key);if (dep) {dep.forEach(effect => effects.add(effect));}effects.forEach(effect => effect()); // 重新执行副作用函数
}// 副作用函数封装(示例)
function effect(fn) {const effectFn = () => {activeEffect = effectFn;fn();activeEffect = null;};effectFn.deps = []; // 存储所有关联的 dep 集合effectFn();
}

1. 核心数据结构:targetMap

类型:WeakMap<Object, Map<string, Set<Effect>>>

作用:全局存储所有响应式对象的依赖关系。

键:被代理的原始对象Object。

值:一个 Map,其键是对象的属性名,值是一个 Set,存储了与该属性相关的所有副作用函数,如组件的渲染函数。

2. track 函数:依赖收集

触发时机:当访问响应式对象的某个属性时,即触发get操作。

核心流程:

1. 获取当前活动的副作用函数:activeEffect 指向当前正在执行的副作用函数,例如组件渲染函数或 watch 回调;

2. 初始化依赖关系:从 targetMap 中获取目标对象 target 对应的 depsMap,若不存在,则新建一个 Map。从 depsMap 中获取属性 key 对应的依赖集合 dep,若不存在,则新建一个 Set;

3. 建立双向关联:将 activeEffect 添加到 dep 中,表示该属性依赖此副作用函数。将 dep 添加到 activeEffect.deps中,用于后续清理无效依赖,避免内存泄漏;

const obj = reactive({ count: 0 });
effect(() => console.log(obj.count));  
// 执行 effect 时,`activeEffect` 指向该函数
// 访问 obj.count 时触发 track,将 effect 函数添加到 count 的依赖集合中。

3. trigger 函数:触发更新

触发时机:当修改响应式对象的属性时 ,即触发set 操作。

核心流程:

1. 获取目标对象的依赖集合:从 targetMap 中获取 target 对应的 depsMap;

2. 收集所有相关副作用函数:从 depsMap 中获取属性 key 对应的 dep,即该属性的所有依赖函数。将dep中的所有 effect 添加到一个临时集合 effects 中;

3. 执行副作用函数:遍历 effects,依次执行每个 effect,触发视图更新或回调逻辑; 

obj.count++;  // 修改 count 时触发 trigger,执行所有依赖 count 的 effect。

4. 关键设计细节

1. WeakMap 的作用:键是弱引用,当目标对象 target 不再被引用时,targetMap 中对应的条目会被自动垃圾回收,避免内存泄漏; 

2. activeEffect 的管理:通过 effect 函数或组件渲染过程,将当前运行的副作用函数赋值给 activeEffect。执行完毕后,activeEffect 会被重置为 null,确保依赖收集的准确性; 

3. 双向依赖关系:effect.deps 存储了所有与该副作用函数相关的依赖集合dep。当副作用函数被销毁时,可以通过遍历 effect.deps 从所有 dep 中移除该函数,避免无效更新; 

4. 性能优化:使用 Set 存储依赖函数,避免重复添加。触发更新时,通过临时集合 effects 确保每个 effect 只执行一次,避免循环触发; 

5. 总结

依赖收集(Track):通过 track 函数,在属性被访问时记录当前活动的副作用函数,建立属性与副作用函数的关联。

触发更新(Trigger):通过 trigger 函数,在属性被修改时找到所有相关副作用函数并执行,实现数据变化到视图更新的响应式机制。

全局依赖关系:targetMap 作为核心数据结构,通过 WeakMap 和嵌套的 Map/Set,高效管理对象、属性和副作用函数之间的映射关系。

相关文章:

  • 天拓四方锂电池卷绕机 PLC 物联网解决方案
  • Maven 插件扩展点与自定义生命周期
  • p024基于Django的网上购物系统的设计与实现
  • 如何免费在线PDF转换成Excel
  • Netty的简单使用
  • 自己手写tomcat项目
  • C++数据结构 —— 平衡树Treap
  • Bellman - Ford 算法与 SPFA 算法求解最短路径问题 ——从零开始的图论讲解(4)
  • OTA与boot loader
  • 基于QT和FFmpeg实现自己的视频播放器FFMediaPlayer(一)——项目总览
  • 38-日语学习小程序
  • Rust 编程语言的官方源码仓库
  • Python爬虫-爬取百度指数之人群兴趣分布数据,进行数据分析
  • Python标准库完全指南:os、sys与math模块详解与实战应用
  • 【论文阅读】人脸修复(face restoration ) 不同先验代表算法整理2
  • 【Java ee初阶】HTTP(2)
  • 【OpenCV】基本数据类型及常见图像模式
  • C++(初阶)(十八)——AVL树
  • JavaScript【5】DOM模型
  • 反射机制动态解析
  • 马上评|训斥打骂女儿致死,无暴力应是“管教”底线
  • 一船明月过沧州:为何这座城敢称“文武双全”?
  • 占地57亩的“潮汕豪宅”面临强制拆除:曾被实施没收,8年间举行5次听证会
  • 张涌任西安市委常委,已卸任西安市副市长职务
  • 观察|本轮印巴冲突或促使印度空军寻求更先进战机
  • 加强战略矿产出口全链条管控将重点开展哪些工作?商务部答问