diff --git a/packages/reactivity/src/watch.ts b/packages/reactivity/src/watch.ts index 96da5ffe5c2..9c1eea00b9b 100644 --- a/packages/reactivity/src/watch.ts +++ b/packages/reactivity/src/watch.ts @@ -206,18 +206,26 @@ export function watch( getter = () => traverse(baseGetter(), depth) } + const scope = getCurrentScope() + const watchHandle: WatchHandle = () => { + effect.stop() + if (scope) { + remove(scope.effects, effect) + } + } + if (once) { if (cb) { const _cb = cb cb = (...args) => { _cb(...args) - effect.stop() + watchHandle() } } else { const _getter = getter getter = () => { _getter() - effect.stop() + watchHandle() } } } @@ -317,14 +325,6 @@ export function watch( effect.run() } - const scope = getCurrentScope() - const watchHandle: WatchHandle = () => { - effect.stop() - if (scope) { - remove(scope.effects, effect) - } - } - watchHandle.pause = effect.pause.bind(effect) watchHandle.resume = effect.resume.bind(effect) watchHandle.stop = watchHandle diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index b1eb85f8a13..7a800949eea 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -1771,6 +1771,11 @@ describe('api: watch', () => { expect(scope.effects.length).toBe(1) unwatch!() expect(scope.effects.length).toBe(0) + + scope.run(() => { + watch(num, () => {}, { once: true, immediate: true }) + }) + expect(scope.effects.length).toBe(0) }) // simplified case of VueUse syncRef