From: Evan You Date: Sun, 31 Dec 2023 09:29:58 +0000 (+0800) Subject: perf(watch): avoid double traverse for reactive source X-Git-Tag: v3.4.4~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=24d77c25ce5d5356adb5367beef1d23e6e340b35;p=thirdparty%2Fvuejs%2Fcore.git perf(watch): avoid double traverse for reactive source --- diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index b25635e664..c82b06c1a8 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -211,6 +211,24 @@ describe('api: watch', () => { expect(cb).toBeCalledTimes(1) }) + it('should still respect deep: true on shallowReactive source', async () => { + const obj = reactive({ a: 1 }) + const arr = shallowReactive([obj]) + + let dummy + watch( + arr, + () => { + dummy = arr[0].a + }, + { deep: true }, + ) + + obj.a++ + await nextTick() + expect(dummy).toBe(2) + }) + it('watching multiple sources', async () => { const state = reactive({ count: 1 }) const count = ref(1) diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index 0c13e72988..d840864454 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -222,7 +222,12 @@ function doWatch( const instance = getCurrentScope() === currentInstance?.scope ? currentInstance : null - // const instance = currentInstance + const reactiveGetter = (source: object) => + deep === true + ? source // traverse will happen in wrapped getter below + : // for shallow or deep: false, only traverse root-level properties + traverse(source, isShallow(source) || deep === false ? 1 : undefined) + let getter: () => any let forceTrigger = false let isMultiSource = false @@ -231,10 +236,7 @@ function doWatch( getter = () => source.value forceTrigger = isShallow(source) } else if (isReactive(source)) { - getter = - isShallow(source) || deep === false - ? () => traverse(source, 1) - : () => traverse(source) + getter = () => reactiveGetter(source) forceTrigger = true } else if (isArray(source)) { isMultiSource = true @@ -244,7 +246,7 @@ function doWatch( if (isRef(s)) { return s.value } else if (isReactive(s)) { - return traverse(s, isShallow(s) || deep === false ? 1 : undefined) + return reactiveGetter(s) } else if (isFunction(s)) { return callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER) } else {