Pārlūkot izejas kodu

fix(watch): should trigger watcher callback on triggerRef when watching ref source

fix #1736
Evan You 5 gadi atpakaļ
vecāks
revīzija
fce2689ff1

+ 25 - 1
packages/runtime-core/__tests__/apiWatch.spec.ts

@@ -12,7 +12,8 @@ import {
   ITERATE_KEY,
   DebuggerEvent,
   TrackOpTypes,
-  TriggerOpTypes
+  TriggerOpTypes,
+  triggerRef
 } from '@vue/reactivity'
 
 // reference: https://vue-composition-api-rfc.netlify.com/api.html#watch
@@ -637,4 +638,27 @@ describe('api: watch', () => {
     v.value++
     expect(calls).toBe(1)
   })
+
+  test('should force trigger on triggerRef when watching a ref', async () => {
+    const v = ref({ a: 1 })
+    let sideEffect = 0
+    watch(v, obj => {
+      sideEffect = obj.a
+    })
+
+    v.value = v.value
+    await nextTick()
+    // should not trigger
+    expect(sideEffect).toBe(0)
+
+    v.value.a++
+    await nextTick()
+    // should not trigger
+    expect(sideEffect).toBe(0)
+
+    triggerRef(v)
+    await nextTick()
+    // should trigger now
+    expect(sideEffect).toBe(2)
+  })
 })

+ 4 - 3
packages/runtime-core/src/apiWatch.ts

@@ -159,8 +159,9 @@ function doWatch(
   }
 
   let getter: () => any
-  if (isRef(source)) {
-    getter = () => source.value
+  const isRefSource = isRef(source)
+  if (isRefSource) {
+    getter = () => (source as Ref).value
   } else if (isReactive(source)) {
     getter = () => source
     deep = true
@@ -239,7 +240,7 @@ function doWatch(
     if (cb) {
       // watch(source, cb)
       const newValue = runner()
-      if (deep || hasChanged(newValue, oldValue)) {
+      if (deep || isRefSource || hasChanged(newValue, oldValue)) {
         // cleanup before running cb again
         if (cleanup) {
           cleanup()