From 4acbf092d908847473d1a329d1928c334cbf5a27 Mon Sep 17 00:00:00 2001 From: LittleSound <464388324@qq.com> Date: Thu, 17 Nov 2022 22:57:01 +0800 Subject: [PATCH] fix(runtime-core): when using the deep mode of watch, watchCallBack will be triggered even if the value does not change (fix #7160) --- .../runtime-core/__tests__/apiWatch.spec.ts | 22 +++++++++++++++++++ packages/runtime-core/src/apiWatch.ts | 16 +++++++------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index f6bad14ddb9..865e1cc7085 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -1150,4 +1150,26 @@ describe('api: watch', () => { // own update effect expect(instance!.scope.effects.length).toBe(1) }) + + // #7160 + test('when using the deep mode of watch, watchCallBack wont be triggered if the value does not change', async () => { + const msg = ref('hi') + const msgTrim = computed(() => msg.value.trim()) + + let changeCounter = 0 + let deepChangeCounter = 0 + + watch(msgTrim, () => ++changeCounter) + watch(msgTrim, () => ++deepChangeCounter, { deep: true }) + + msg.value = 'hi!' + await nextTick() + expect(changeCounter).toBe(1) + expect(deepChangeCounter).toBe(1) + + msg.value = 'hi! ' + await nextTick() + expect(changeCounter).toBe(1) + expect(deepChangeCounter).toBe(1) + }) }) diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index ce13f0bb805..4fbcdd4ad0b 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -311,13 +311,13 @@ function doWatch( // watch(source, cb) const newValue = effect.run() if ( - deep || forceTrigger || (isMultiSource - ? (newValue as any[]).some((v, i) => - hasChanged(v, (oldValue as any[])[i]) + ? (newValue as any[]).some( + (v, i) => + (deep && isObject(v)) || hasChanged(v, (oldValue as any[])[i]) ) - : hasChanged(newValue, oldValue)) || + : (deep && isObject(newValue)) || hasChanged(newValue, oldValue)) || (__COMPAT__ && isArray(newValue) && isCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance)) @@ -329,11 +329,11 @@ function doWatch( callWithAsyncErrorHandling(cb, instance, ErrorCodes.WATCH_CALLBACK, [ newValue, // pass undefined as the old value when it's changed for the first time - oldValue === INITIAL_WATCHER_VALUE + oldValue === INITIAL_WATCHER_VALUE ? undefined - : (isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE) - ? [] - : oldValue, + : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE + ? [] + : oldValue, onCleanup ]) oldValue = newValue