]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
perf(watch): avoid double traverse for reactive source
authorEvan You <yyx990803@gmail.com>
Sun, 31 Dec 2023 09:29:58 +0000 (17:29 +0800)
committerEvan You <yyx990803@gmail.com>
Sun, 31 Dec 2023 09:29:58 +0000 (17:29 +0800)
packages/runtime-core/__tests__/apiWatch.spec.ts
packages/runtime-core/src/apiWatch.ts

index b25635e664e741b17f44df7443a2ba340729937e..c82b06c1a8b02715cb0b49e781e8124f5a5064c7 100644 (file)
@@ -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)
index 0c13e72988f6d18f717f6e5436b7a00ab5895371..d840864454ffa87e76227a881d8de6c038670a68 100644 (file)
@@ -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 {