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
 |     // should not track b as dependency of Child
 | ||||||
|     expect(updated).toHaveBeenCalledTimes(1) |     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 { | ): WatchStopHandle { | ||||||
|   const publicThis = this.proxy as any |   const publicThis = this.proxy as any | ||||||
|   const getter = isString(source) |   const getter = isString(source) | ||||||
|     ? () => publicThis[source] |     ? source.includes('.') | ||||||
|  |       ? createPathGetter(publicThis, source) | ||||||
|  |       : () => publicThis[source] | ||||||
|     : source.bind(publicThis) |     : source.bind(publicThis) | ||||||
|   return doWatch(getter, cb.bind(publicThis), options, this) |   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()) { | function traverse(value: unknown, seen: Set<unknown> = new Set()) { | ||||||
|   if (!isObject(value) || seen.has(value)) { |   if (!isObject(value) || seen.has(value)) { | ||||||
|     return value |     return value | ||||||
|  | |||||||
| @ -20,7 +20,12 @@ import { | |||||||
|   isPromise |   isPromise | ||||||
| } from '@vue/shared' | } from '@vue/shared' | ||||||
| import { computed } from './apiComputed' | import { computed } from './apiComputed' | ||||||
| import { watch, WatchOptions, WatchCallback } from './apiWatch' | import { | ||||||
|  |   watch, | ||||||
|  |   WatchOptions, | ||||||
|  |   WatchCallback, | ||||||
|  |   createPathGetter | ||||||
|  | } from './apiWatch' | ||||||
| import { provide, inject } from './apiInject' | import { provide, inject } from './apiInject' | ||||||
| import { | import { | ||||||
|   onBeforeMount, |   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( | export function resolveMergedOptions( | ||||||
|   instance: ComponentInternalInstance |   instance: ComponentInternalInstance | ||||||
| ): ComponentOptions { | ): ComponentOptions { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user