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