}
}
-function traverse(value: unknown, seen: Set<unknown> = new Set()) {
- if (
- !isObject(value) ||
- seen.has(value) ||
- (value as any)[ReactiveFlags.SKIP]
- ) {
+export function traverse(value: unknown, seen: Set<unknown> = new Set()) {
+ if (!isObject(value) || (value as any)[ReactiveFlags.SKIP]) {
+ return value
+ }
+ seen = seen || new Set()
+ if (seen.has(value)) {
return value
}
seen.add(value)
import { ComponentPublicInstance } from './componentPublicInstance'
import { mapCompatDirectiveHook } from './compat/customDirective'
import { pauseTracking, resetTracking } from '@vue/reactivity'
+import { traverse } from './apiWatch'
export interface DirectiveBinding<V = any> {
instance: ComponentPublicInstance | null
beforeUnmount?: DirectiveHook<T, null, V>
unmounted?: DirectiveHook<T, null, V>
getSSRProps?: SSRDirectiveHook
+ deep?: boolean
}
export type FunctionDirective<T = any, V = any> = DirectiveHook<T, any, V>
updated: dir
} as ObjectDirective
}
+ if (dir.deep) {
+ traverse(value)
+ }
bindings.push({
dir,
instance,
}
export const vModelCheckbox: ModelDirective<HTMLInputElement> = {
+ // #4096 array checkboxes need to be deep traversed
+ deep: true,
created(el, _, vnode) {
el._assign = getModelAssigner(vnode)
addEventListener(el, 'change', () => {
}
export const vModelSelect: ModelDirective<HTMLSelectElement> = {
+ // <select multiple> value need to be deep traversed
+ deep: true,
created(el, { value, modifiers: { number } }, vnode) {
const isSetModel = isSet(value)
addEventListener(el, 'change', () => {