From 668ecda6104723ba031557cc6b3abc191ee9826b Mon Sep 17 00:00:00 2001 From: dj <1042039504@qq.com> Date: Wed, 4 Feb 2026 23:25:32 +0800 Subject: [PATCH] =?UTF-8?q?refactor(reactivity):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=93=8D=E5=BA=94=E5=BC=8F=E7=B3=BB=E7=BB=9F=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E6=94=B6=E9=9B=86=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将依赖管理逻辑分离到独立的dep模块 - 创建Dep类型定义和createDep工厂函数 - 修改KeyToDepMap类型以使用Dep集合替代单个ReactiveEffect - 添加trackEffects函数用于统一跟踪依赖 - 实现triggerEffects函数用于批量触发依赖 - 增加triggerEffect函数用于触发单个依赖 - 在effect运行时添加注释说明首次getter触发 - 添加HTML示例文件验证多依赖收集功能 --- packages/reactivity/src/dep.ts | 7 +++ packages/reactivity/src/effect.ts | 52 +++++++++++++++---- .../vue/examples/reactivity/reactive-dep.html | 29 +++++++++++ 3 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 packages/reactivity/src/dep.ts create mode 100644 packages/vue/examples/reactivity/reactive-dep.html diff --git a/packages/reactivity/src/dep.ts b/packages/reactivity/src/dep.ts new file mode 100644 index 0000000..46718a3 --- /dev/null +++ b/packages/reactivity/src/dep.ts @@ -0,0 +1,7 @@ +import { ReactiveEffect } from './effect' + +export type Dep = Set +export const createDep = (effects?: ReactiveEffect[]): Dep => { + const dep = new Set(effects) as Dep + return dep +} diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 59eac4a..7c40214 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -1,4 +1,7 @@ -type KeyToDepMap = Map +import { createDep, Dep } from './dep' +import { isArray } from '@vue/shared' + +type KeyToDepMap = Map /** * 收集所有依赖的WeakMap实例 * key: 响应性对象 @@ -18,8 +21,9 @@ export let activeEffect: ReactiveEffect | undefined export class ReactiveEffect { constructor(public fn: () => T) {} run() { + //当前被激活的effect实例 activeEffect = this - return this.fn() + return this.fn() //完成第一次getter行为的触发 } } @@ -36,9 +40,20 @@ export function track(target: object, key: unknown) { if (!depsMap) { targetMap.set(target, (depsMap = new Map())) } - //为指定map, 指定key, 设置回调函数 - depsMap.set(key, activeEffect) - console.log(targetMap) + + let dep = depsMap.get(key) + if (!dep) { + depsMap.set(key, (dep = createDep())) + } + + trackEffects(dep) +} + +/** + * 利用dep依次跟踪指定key的所有effect + */ +export function trackEffects(dep: Dep) { + dep.add(activeEffect!) } /** @@ -53,10 +68,29 @@ export function trigger(target: object, key: unknown, newValue: unknown) { return } //依据key, 从depsMap中取出value, 该value是一个ReactiveEffect类型的数据 - const effect = depsMap.get(key) as ReactiveEffect - if (!effect) { + const dep: Dep | undefined = depsMap.get(key) + if (!dep) { return } - //执行effect中保存的fn函数 - effect.fn() + triggerEffects(dep) +} + +/** + * 依次触发dep中保存的依赖 + * @param dep + */ +export function triggerEffects(dep: Dep) { + const effects = isArray(dep) ? dep : [...dep] + //依次触发依赖 + for (const effect of effects) { + triggerEffect(effect) + } +} + +/** + * 触发指定依赖 + * @param effect + */ +export function triggerEffect(effect: ReactiveEffect) { + effect.run() } diff --git a/packages/vue/examples/reactivity/reactive-dep.html b/packages/vue/examples/reactivity/reactive-dep.html new file mode 100644 index 0000000..15ec2df --- /dev/null +++ b/packages/vue/examples/reactivity/reactive-dep.html @@ -0,0 +1,29 @@ + + + + + Document + + + +
+

+

+
+ + + \ No newline at end of file