feat: dot-delimited path for watch
This commit is contained in:
parent
a848466f07
commit
296164c207
@ -1,4 +1,4 @@
|
|||||||
import { EMPTY_OBJ } from './utils'
|
import { EMPTY_OBJ, NOOP } from './utils'
|
||||||
import { MountedComponent } from './component'
|
import { MountedComponent } from './component'
|
||||||
import { ComponentWatchOptions, WatchOptions } from './componentOptions'
|
import { ComponentWatchOptions, WatchOptions } from './componentOptions'
|
||||||
import { autorun, stop } from '@vue/observer'
|
import { autorun, stop } from '@vue/observer'
|
||||||
@ -36,9 +36,17 @@ export function setupWatcher(
|
|||||||
|
|
||||||
const rawGetter =
|
const rawGetter =
|
||||||
typeof keyOrFn === 'string'
|
typeof keyOrFn === 'string'
|
||||||
? () => proxy[keyOrFn]
|
? parseDotPath(keyOrFn, proxy)
|
||||||
: () => keyOrFn.call(proxy)
|
: () => keyOrFn.call(proxy)
|
||||||
|
|
||||||
|
if (__DEV__ && rawGetter === NOOP) {
|
||||||
|
console.warn(
|
||||||
|
`Failed watching expression: "${keyOrFn}". ` +
|
||||||
|
`Watch expressions can only be dot-delimited paths. ` +
|
||||||
|
`For more complex expressions, use $watch with a function instead.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const getter = options.deep ? () => traverse(rawGetter()) : rawGetter
|
const getter = options.deep ? () => traverse(rawGetter()) : rawGetter
|
||||||
|
|
||||||
let oldValue: any
|
let oldValue: any
|
||||||
@ -85,6 +93,27 @@ export function teardownWatch(instance: MountedComponent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bailRE = /[^\w.$]/
|
||||||
|
|
||||||
|
function parseDotPath(path: string, ctx: any): Function {
|
||||||
|
if (bailRE.test(path)) {
|
||||||
|
return NOOP
|
||||||
|
}
|
||||||
|
const segments = path.split('.')
|
||||||
|
if (segments.length === 1) {
|
||||||
|
return () => ctx[path]
|
||||||
|
} else {
|
||||||
|
return () => {
|
||||||
|
let obj = ctx
|
||||||
|
for (let i = 0; i < segments.length; i++) {
|
||||||
|
if (!obj) return
|
||||||
|
obj = obj[segments[i]]
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function traverse(value: any, seen: Set<any> = new Set()) {
|
function traverse(value: any, seen: Set<any> = new Set()) {
|
||||||
if (value === null || typeof value !== 'object' || seen.has(value)) {
|
if (value === null || typeof value !== 'object' || seen.has(value)) {
|
||||||
return
|
return
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
export const EMPTY_OBJ: { readonly [key: string]: any } = Object.freeze({})
|
export const EMPTY_OBJ: { readonly [key: string]: any } = Object.freeze({})
|
||||||
|
|
||||||
|
export const NOOP = () => {}
|
||||||
|
|
||||||
export const isReservedProp = (key: string): boolean => {
|
export const isReservedProp = (key: string): boolean => {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'key':
|
case 'key':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user