fix(watch): this.$watch should support watching keypath
This commit is contained in:
		
							parent
							
								
									0f2d8f3244
								
							
						
					
					
						commit
						870f2a7ba3
					
				| @ -915,4 +915,33 @@ describe('api: watch', () => { | ||||
|     // should not track b as dependency of Child
 | ||||
|     expect(updated).toHaveBeenCalledTimes(1) | ||||
|   }) | ||||
| 
 | ||||
|   test('watching keypath', async () => { | ||||
|     const spy = jest.fn() | ||||
|     const Comp = defineComponent({ | ||||
|       render() {}, | ||||
|       data() { | ||||
|         return { | ||||
|           a: { | ||||
|             b: 1 | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       watch: { | ||||
|         'a.b': spy | ||||
|       }, | ||||
|       created(this: any) { | ||||
|         this.$watch('a.b', spy) | ||||
|       }, | ||||
|       mounted(this: any) { | ||||
|         this.a.b++ | ||||
|       } | ||||
|     }) | ||||
| 
 | ||||
|     const root = nodeOps.createElement('div') | ||||
|     createApp(Comp).mount(root) | ||||
| 
 | ||||
|     await nextTick() | ||||
|     expect(spy).toHaveBeenCalledTimes(2) | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| @ -334,11 +334,24 @@ export function instanceWatch( | ||||
| ): WatchStopHandle { | ||||
|   const publicThis = this.proxy as any | ||||
|   const getter = isString(source) | ||||
|     ? () => publicThis[source] | ||||
|     ? source.includes('.') | ||||
|       ? createPathGetter(publicThis, source) | ||||
|       : () => publicThis[source] | ||||
|     : source.bind(publicThis) | ||||
|   return doWatch(getter, cb.bind(publicThis), options, this) | ||||
| } | ||||
| 
 | ||||
| export 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 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function traverse(value: unknown, seen: Set<unknown> = new Set()) { | ||||
|   if (!isObject(value) || seen.has(value)) { | ||||
|     return value | ||||
|  | ||||
| @ -20,7 +20,12 @@ import { | ||||
|   isPromise | ||||
| } from '@vue/shared' | ||||
| import { computed } from './apiComputed' | ||||
| import { watch, WatchOptions, WatchCallback } from './apiWatch' | ||||
| import { | ||||
|   watch, | ||||
|   WatchOptions, | ||||
|   WatchCallback, | ||||
|   createPathGetter | ||||
| } from './apiWatch' | ||||
| import { provide, inject } from './apiInject' | ||||
| import { | ||||
|   onBeforeMount, | ||||
| @ -939,17 +944,6 @@ function createWatcher( | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export function resolveMergedOptions( | ||||
|   instance: ComponentInternalInstance | ||||
| ): ComponentOptions { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user