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…
Reference in New Issue
Block a user