diff --git a/packages/observer/src/effect.ts b/packages/observer/src/effect.ts index e7438f52..95d93a38 100644 --- a/packages/observer/src/effect.ts +++ b/packages/observer/src/effect.ts @@ -11,6 +11,7 @@ export interface ReactiveEffect { scheduler?: Scheduler onTrack?: Debugger onTrigger?: Debugger + onStop?: () => void } export interface ReactiveEffectOptions { @@ -19,6 +20,7 @@ export interface ReactiveEffectOptions { scheduler?: Scheduler onTrack?: Debugger onTrigger?: Debugger + onStop?: () => void } export type Scheduler = (run: () => any) => void @@ -49,6 +51,7 @@ export function createReactiveEffect( effect.scheduler = options.scheduler effect.onTrack = options.onTrack effect.onTrigger = options.onTrigger + effect.onStop = options.onStop effect.computed = options.computed effect.deps = [] return effect diff --git a/packages/observer/src/index.ts b/packages/observer/src/index.ts index 0e8781eb..cf575ec4 100644 --- a/packages/observer/src/index.ts +++ b/packages/observer/src/index.ts @@ -134,6 +134,9 @@ export function effect( export function stop(effect: ReactiveEffect) { if (effect.active) { cleanup(effect) + if (effect.onStop) { + effect.onStop() + } effect.active = false } } diff --git a/packages/runtime-core/src/reactivity.ts b/packages/runtime-core/src/reactivity.ts index 2b0e9f2f..4c28185a 100644 --- a/packages/runtime-core/src/reactivity.ts +++ b/packages/runtime-core/src/reactivity.ts @@ -83,10 +83,15 @@ export function watch( const newValue = runner() if (options.deep || newValue !== oldValue) { try { - if (isFunction(cleanup)) { + // cleanup before running cb again + if (cleanup) { cleanup() } - cleanup = cb(newValue, oldValue) + const _cleanup = cb(newValue, oldValue) + if (isFunction(_cleanup)) { + // save cleanup so it is also called when effect is stopped + cleanup = runner.onStop = _cleanup + } } catch (e) { // TODO handle error // handleError(e, instance, ErrorTypes.WATCH_CALLBACK)