From 39a78ec90931e6b8df32637bd359efd2f1a738cc Mon Sep 17 00:00:00 2001 From: Jayden12138 <18993882884@163.com> Date: Wed, 20 Mar 2024 15:24:37 +0800 Subject: [PATCH] fix: nested effect --- packages/reactivity/__tests__/effect.spec.ts | 33 ++++++++++++++++ packages/reactivity/src/effect.ts | 41 +++++++++++++------- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/packages/reactivity/__tests__/effect.spec.ts b/packages/reactivity/__tests__/effect.spec.ts index 2d098712..f0d3735b 100644 --- a/packages/reactivity/__tests__/effect.spec.ts +++ b/packages/reactivity/__tests__/effect.spec.ts @@ -117,4 +117,37 @@ describe("effect", () => { stop(runner); expect(onStop).toHaveBeenCalled(); }); + + it('should correctly track the order of nested effects', () => { + const counter = reactive({ + outerCount: 0, + innerCount: 0, + }) + + let executionOrder: string[] = [] + + effect(() => { + effect(() => { + counter.innerCount + executionOrder.push('inner') + }) + counter.outerCount + executionOrder.push('outer') + }) + + // init effect + expect(executionOrder).toEqual(['inner', 'outer']) + + // reset + executionOrder = [] + + counter.outerCount++ + expect(executionOrder).toEqual(['inner', 'outer']) + + // reset + executionOrder = [] + + counter.innerCount++ + expect(executionOrder).toEqual(['inner', 'inner']) + }) }); diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index cdc21a45..d981beb0 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -27,21 +27,32 @@ export class ReactiveEffect { return this.fn(); } - // 执行 fn 收集依赖 - // 可以开始收集依赖了 - shouldTrack = true; - - // 执行的时候给全局的 activeEffect 赋值 - // 利用全局属性来获取当前的 effect - activeEffect = this as any; - // 执行用户传入的 fn - console.log("执行用户传入的 fn"); - const result = this.fn(); - // 重置 - shouldTrack = false; - activeEffect = undefined; - - return result; + // 保存嵌套effect外层effect的 activeEffect 和 shouldTrack + let lastEffect = activeEffect; + let lastShouldTrack = shouldTrack; + + try { + // 执行 fn 收集依赖 + // 可以开始收集依赖了 + shouldTrack = true; + + // 执行的时候给全局的 activeEffect 赋值 + // 利用全局属性来获取当前的 effect + activeEffect = this as any; + // 执行用户传入的 fn + console.log("执行用户传入的 fn"); + const result = this.fn(); + // 重置 + shouldTrack = false; + activeEffect = undefined; + + return result; + } finally { + // 内层 effect 执行完毕 + // 取出外层 effect 的 activeEffect 和 shouldTrack + activeEffect = lastEffect; + shouldTrack = lastShouldTrack; + } } stop() {