From 0850e05bd13d986d84e979144e4f7393858a92e6 Mon Sep 17 00:00:00 2001 From: dj <1042039504@qq.com> Date: Wed, 4 Feb 2026 22:19:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(effects):=20=E5=AE=9E=E7=8E=B0=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E5=BC=8F=E4=BE=9D=E8=B5=96=E6=94=B6=E9=9B=86=E5=92=8C?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建targetMap WeakMap用于存储响应式对象及其依赖映射关系 - 实现track函数用于收集依赖并建立target-key-effect的映射 - 实现trigger函数用于触发指定key的依赖更新 - 在track中通过activeEffect判断是否需要收集依赖 - 添加详细的JSDoc注释说明参数和功能 - 示例页面中添加定时器验证响应式更新效果 --- packages/reactivity/src/effect.ts | 43 ++++++++++++++++--- .../vue/examples/reactivity/reactive.html | 3 ++ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index b593b86..59eac4a 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -1,3 +1,13 @@ +type KeyToDepMap = Map +/** + * 收集所有依赖的WeakMap实例 + * key: 响应性对象 + * value: Map对象 + * key: 响应性对象的指定属性 + * value:指定对象的指定属性的执行函数 + */ +const targetMap = new WeakMap() + export function effect(fn: () => T) { const _effect = new ReactiveEffect(fn) _effect.run() @@ -15,19 +25,38 @@ export class ReactiveEffect { /** * 收集依赖 - * @param target - * @param key + * @param target WeakMap的key + * @param key key代理对象的key, 当依赖被触发时,需要根据该key获取 */ export function track(target: object, key: unknown) { - console.log('收集依赖 track') + if (!activeEffect) return + //尝试从 targetMap 中, 根据target获取map + let depsMap = targetMap.get(target) + //如果获取到的map不存在,则生成新的map对象, 并把该对象赋值给对应的value + if (!depsMap) { + targetMap.set(target, (depsMap = new Map())) + } + //为指定map, 指定key, 设置回调函数 + depsMap.set(key, activeEffect) + console.log(targetMap) } /** * 触发依赖 - * @param target - * @param key - * @param newValue + * @param target WeakMap的key + * @param key key代理对象的key, 当依赖被触发时,需要根据该key获取 */ export function trigger(target: object, key: unknown, newValue: unknown) { - console.log('触发依赖 trigger') + //依据target获取存储的map实例 + const depsMap = targetMap.get(target) + if (!depsMap) { + return + } + //依据key, 从depsMap中取出value, 该value是一个ReactiveEffect类型的数据 + const effect = depsMap.get(key) as ReactiveEffect + if (!effect) { + return + } + //执行effect中保存的fn函数 + effect.fn() } diff --git a/packages/vue/examples/reactivity/reactive.html b/packages/vue/examples/reactivity/reactive.html index f23a65f..d232889 100644 --- a/packages/vue/examples/reactivity/reactive.html +++ b/packages/vue/examples/reactivity/reactive.html @@ -16,5 +16,8 @@ effect(()=>{ document.querySelector('#app').innerText=obj.name }) + setTimeout(()=>{ + obj.name='李四' + },2000) \ No newline at end of file