Просмотр исходного кода

fix(reactivity): fix watch behavior inconsistency + deep ref shallow check

fix #12643
Evan You 3 лет назад
Родитель
Сommit
98fb01c79c
3 измененных файлов с 22 добавлено и 7 удалено
  1. 4 6
      src/v3/apiWatch.ts
  2. 1 1
      src/v3/reactivity/ref.ts
  3. 17 0
      test/unit/features/v3/apiWatch.spec.ts

+ 4 - 6
src/v3/apiWatch.ts

@@ -196,12 +196,10 @@ function doWatch(
     getter = () => source.value
     forceTrigger = isShallow(source)
   } else if (isReactive(source)) {
-    getter = isArray(source)
-      ? () => {
-          ;(source as any).__ob__.dep.depend()
-          return source
-        }
-      : () => source
+    getter = () => {
+      ;(source as any).__ob__.dep.depend()
+      return source
+    }
     deep = true
   } else if (isArray(source)) {
     isMultiSource = true

+ 1 - 1
src/v3/reactivity/ref.ts

@@ -68,7 +68,7 @@ function createRef(rawValue: unknown, shallow: boolean) {
   }
   const ref: any = {}
   def(ref, RefFlag, true)
-  def(ref, ReactiveFlags.IS_SHALLOW, true)
+  def(ref, ReactiveFlags.IS_SHALLOW, shallow)
   def(
     ref,
     'dep',

+ 17 - 0
test/unit/features/v3/apiWatch.spec.ts

@@ -1136,4 +1136,21 @@ describe('api: watch', () => {
     await nextTick()
     expect(spy).toHaveBeenCalledTimes(2)
   })
+
+  // #12643
+  test('should trigger watch on reactive object when new property is added via set()', () => {
+    const spy = vi.fn()
+    const obj = reactive({})
+    watch(obj, spy, { flush: 'sync' })
+    set(obj, 'foo', 1)
+    expect(spy).toHaveBeenCalled()
+  })
+
+  test('should not trigger watch when calling set() on ref value', () => {
+    const spy = vi.fn()
+    const r = ref({})
+    watch(r, spy, { flush: 'sync' })
+    set(r.value, 'foo', 1)
+    expect(spy).not.toHaveBeenCalled()
+  })
 })