Browse Source

feat(watch): support dot-delimited path in watch option

Evan You 5 years ago
parent
commit
1c9a0b3e19

+ 12 - 2
packages/runtime-core/__tests__/apiOptions.spec.ts

@@ -113,6 +113,7 @@ describe('api: options', () => {
     const spyB = jest.fn(returnThis)
     const spyC = jest.fn(returnThis)
     const spyD = jest.fn(returnThis)
+    const spyE = jest.fn(returnThis)
 
     let ctx: any
     const Comp = {
@@ -123,7 +124,10 @@ describe('api: options', () => {
           baz: {
             qux: 3
           },
-          qux: 4
+          qux: 4,
+          dot: {
+            path: 5
+          }
         }
       },
       watch: {
@@ -137,7 +141,8 @@ describe('api: options', () => {
         },
         qux: {
           handler: 'onQuxChange'
-        }
+        },
+        'dot.path': spyE
       },
       methods: {
         onFooChange: spyA,
@@ -175,6 +180,11 @@ describe('api: options', () => {
     await nextTick()
     expect(spyD).toHaveBeenCalledTimes(1)
     assertCall(spyD, 0, [5, 4])
+
+    ctx.dot.path++
+    await nextTick()
+    expect(spyE).toHaveBeenCalledTimes(1)
+    assertCall(spyE, 0, [6, 5])
   })
 
   test('watch array', async () => {

+ 15 - 2
packages/runtime-core/src/componentOptions.ts

@@ -816,7 +816,9 @@ function createWatcher(
   publicThis: ComponentPublicInstance,
   key: string
 ) {
-  const getter = () => (publicThis as any)[key]
+  const getter = key.includes('.')
+    ? createPathGetter(publicThis, key)
+    : () => (publicThis as any)[key]
   if (isString(raw)) {
     const handler = ctx[raw]
     if (isFunction(handler)) {
@@ -840,7 +842,18 @@ function createWatcher(
       }
     }
   } else if (__DEV__) {
-    warn(`Invalid watch option: "${key}"`)
+    warn(`Invalid watch option: "${key}"`, raw)
+  }
+}
+
+function createPathGetter(ctx: any, path: string) {
+  const segments = path.split('.')
+  return () => {
+    let cur = ctx
+    for (let i = 0; i < segments.length && cur; i++) {
+      cur = cur[segments[i]]
+    }
+    return cur
   }
 }