mirror of https://github.com/vuejs/core.git
fix(compat): watch arrays as deep: 1
This commit is contained in:
parent
5d04c062d6
commit
351ce069c5
|
@ -245,7 +245,8 @@ export function watch(
|
||||||
forceTrigger ||
|
forceTrigger ||
|
||||||
(isMultiSource
|
(isMultiSource
|
||||||
? (newValue as any[]).some((v, i) => hasChanged(v, oldValue[i]))
|
? (newValue as any[]).some((v, i) => hasChanged(v, oldValue[i]))
|
||||||
: hasChanged(newValue, oldValue))
|
: hasChanged(newValue, oldValue)) ||
|
||||||
|
(__COMPAT__ && (options as any).compatWatchArray && isArray(newValue))
|
||||||
) {
|
) {
|
||||||
// cleanup before running cb again
|
// cleanup before running cb again
|
||||||
if (cleanup) {
|
if (cleanup) {
|
||||||
|
@ -264,15 +265,6 @@ export function watch(
|
||||||
: oldValue,
|
: oldValue,
|
||||||
boundCleanup,
|
boundCleanup,
|
||||||
]
|
]
|
||||||
|
|
||||||
if (__COMPAT__) {
|
|
||||||
for (let i = 0; i < args.length - 1; i++) {
|
|
||||||
if (args[i] && args[i].WATCH_ARRAY_UNWRAP) {
|
|
||||||
args[i] = args[i].WATCH_ARRAY_UNWRAP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
oldValue = newValue
|
oldValue = newValue
|
||||||
call
|
call
|
||||||
? call(cb!, WatchErrorCodes.WATCH_CALLBACK, args)
|
? call(cb!, WatchErrorCodes.WATCH_CALLBACK, args)
|
||||||
|
|
|
@ -7,9 +7,17 @@ import {
|
||||||
type WatchHandle,
|
type WatchHandle,
|
||||||
type WatchSource,
|
type WatchSource,
|
||||||
watch as baseWatch,
|
watch as baseWatch,
|
||||||
|
traverse,
|
||||||
} from '@vue/reactivity'
|
} from '@vue/reactivity'
|
||||||
import { type SchedulerJob, SchedulerJobFlags, queueJob } from './scheduler'
|
import { type SchedulerJob, SchedulerJobFlags, queueJob } from './scheduler'
|
||||||
import { EMPTY_OBJ, NOOP, extend, isFunction, isString } from '@vue/shared'
|
import {
|
||||||
|
EMPTY_OBJ,
|
||||||
|
NOOP,
|
||||||
|
extend,
|
||||||
|
isArray,
|
||||||
|
isFunction,
|
||||||
|
isString,
|
||||||
|
} from '@vue/shared'
|
||||||
import {
|
import {
|
||||||
type ComponentInternalInstance,
|
type ComponentInternalInstance,
|
||||||
currentInstance,
|
currentInstance,
|
||||||
|
@ -19,6 +27,11 @@ import {
|
||||||
import { callWithAsyncErrorHandling } from './errorHandling'
|
import { callWithAsyncErrorHandling } from './errorHandling'
|
||||||
import { queuePostRenderEffect } from './renderer'
|
import { queuePostRenderEffect } from './renderer'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
|
import {
|
||||||
|
DeprecationTypes,
|
||||||
|
checkCompatEnabled,
|
||||||
|
isCompatEnabled,
|
||||||
|
} from './compat/compatConfig'
|
||||||
import type { ObjectWatchOptionItem } from './componentOptions'
|
import type { ObjectWatchOptionItem } from './componentOptions'
|
||||||
import { useSSRContext } from './helpers/useSsrContext'
|
import { useSSRContext } from './helpers/useSsrContext'
|
||||||
|
|
||||||
|
@ -236,6 +249,22 @@ function doWatch(
|
||||||
return watchHandle
|
return watchHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createCompatWatchGetter(
|
||||||
|
baseGetter: () => any,
|
||||||
|
instance: ComponentInternalInstance,
|
||||||
|
) {
|
||||||
|
return (): any => {
|
||||||
|
const val = baseGetter()
|
||||||
|
if (
|
||||||
|
isArray(val) &&
|
||||||
|
checkCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance)
|
||||||
|
) {
|
||||||
|
traverse(val, 1)
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// this.$watch
|
// this.$watch
|
||||||
export function instanceWatch(
|
export function instanceWatch(
|
||||||
this: ComponentInternalInstance,
|
this: ComponentInternalInstance,
|
||||||
|
@ -244,7 +273,7 @@ export function instanceWatch(
|
||||||
options?: WatchOptions,
|
options?: WatchOptions,
|
||||||
): WatchHandle {
|
): WatchHandle {
|
||||||
const publicThis = this.proxy as any
|
const publicThis = this.proxy as any
|
||||||
const getter = isString(source)
|
let getter = isString(source)
|
||||||
? source.includes('.')
|
? source.includes('.')
|
||||||
? createPathGetter(publicThis, source)
|
? createPathGetter(publicThis, source)
|
||||||
: () => publicThis[source]
|
: () => publicThis[source]
|
||||||
|
@ -256,6 +285,19 @@ export function instanceWatch(
|
||||||
cb = value.handler as Function
|
cb = value.handler as Function
|
||||||
options = value
|
options = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
__COMPAT__ &&
|
||||||
|
isString(source) &&
|
||||||
|
isCompatEnabled(DeprecationTypes.WATCH_ARRAY, this)
|
||||||
|
) {
|
||||||
|
const deep = options && options.deep
|
||||||
|
if (!deep) {
|
||||||
|
options = extend({ compatWatchArray: true }, options)
|
||||||
|
getter = createCompatWatchGetter(getter, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const reset = setCurrentInstance(this)
|
const reset = setCurrentInstance(this)
|
||||||
const res = doWatch(getter, cb.bind(publicThis), options)
|
const res = doWatch(getter, cb.bind(publicThis), options)
|
||||||
reset()
|
reset()
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import {
|
import type {
|
||||||
type Component,
|
Component,
|
||||||
type ComponentInternalInstance,
|
ComponentInternalInstance,
|
||||||
type ComponentInternalOptions,
|
ComponentInternalOptions,
|
||||||
type ConcreteComponent,
|
ConcreteComponent,
|
||||||
type Data,
|
Data,
|
||||||
type InternalRenderFunction,
|
InternalRenderFunction,
|
||||||
type SetupContext,
|
SetupContext,
|
||||||
currentInstance,
|
|
||||||
} from './component'
|
} from './component'
|
||||||
import {
|
import {
|
||||||
type LooseRequired,
|
type LooseRequired,
|
||||||
|
@ -19,11 +18,12 @@ import {
|
||||||
isPromise,
|
isPromise,
|
||||||
isString,
|
isString,
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { type Ref, getCurrentScope, isRef, traverse } from '@vue/reactivity'
|
import { type Ref, isRef } from '@vue/reactivity'
|
||||||
import { computed } from './apiComputed'
|
import { computed } from './apiComputed'
|
||||||
import {
|
import {
|
||||||
type WatchCallback,
|
type WatchCallback,
|
||||||
type WatchOptions,
|
type WatchOptions,
|
||||||
|
createCompatWatchGetter,
|
||||||
createPathGetter,
|
createPathGetter,
|
||||||
watch,
|
watch,
|
||||||
} from './apiWatch'
|
} from './apiWatch'
|
||||||
|
@ -72,9 +72,9 @@ import { warn } from './warning'
|
||||||
import type { VNodeChild } from './vnode'
|
import type { VNodeChild } from './vnode'
|
||||||
import { callWithAsyncErrorHandling } from './errorHandling'
|
import { callWithAsyncErrorHandling } from './errorHandling'
|
||||||
import { deepMergeData } from './compat/data'
|
import { deepMergeData } from './compat/data'
|
||||||
import { DeprecationTypes, checkCompatEnabled } from './compat/compatConfig'
|
|
||||||
import {
|
import {
|
||||||
type CompatConfig,
|
type CompatConfig,
|
||||||
|
DeprecationTypes,
|
||||||
isCompatEnabled,
|
isCompatEnabled,
|
||||||
softAssertCompatEnabled,
|
softAssertCompatEnabled,
|
||||||
} from './compat/compatConfig'
|
} from './compat/compatConfig'
|
||||||
|
@ -843,7 +843,7 @@ function callHook(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createWatcher(
|
function createWatcher(
|
||||||
raw: ComponentWatchOptionItem,
|
raw: ComponentWatchOptionItem,
|
||||||
ctx: Data,
|
ctx: Data,
|
||||||
publicThis: ComponentPublicInstance,
|
publicThis: ComponentPublicInstance,
|
||||||
|
@ -854,23 +854,14 @@ export function createWatcher(
|
||||||
: () => (publicThis as any)[key]
|
: () => (publicThis as any)[key]
|
||||||
|
|
||||||
const options: WatchOptions = {}
|
const options: WatchOptions = {}
|
||||||
if (__COMPAT__) {
|
if (
|
||||||
const instance =
|
__COMPAT__ &&
|
||||||
currentInstance && getCurrentScope() === currentInstance.scope
|
isCompatEnabled(DeprecationTypes.WATCH_ARRAY, publicThis.$)
|
||||||
? currentInstance
|
) {
|
||||||
: null
|
const deep = isObject(raw) && !isArray(raw) && !isFunction(raw) && raw.deep
|
||||||
|
if (!deep) {
|
||||||
const baseGetter = getter
|
;(options as any).compatWatchArray = true
|
||||||
getter = () => {
|
getter = createCompatWatchGetter(getter, publicThis.$)
|
||||||
const val = baseGetter()
|
|
||||||
if (
|
|
||||||
isArray(val) &&
|
|
||||||
checkCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance)
|
|
||||||
) {
|
|
||||||
traverse(val, 1)
|
|
||||||
return { WATCH_ARRAY_UNWRAP: val }
|
|
||||||
}
|
|
||||||
return val
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,54 +47,377 @@ test('mode as function', () => {
|
||||||
expect(vm.$el.innerHTML).toBe(`<div>foo</div><div>bar</div>`)
|
expect(vm.$el.innerHTML).toBe(`<div>foo</div><div>bar</div>`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('WATCH_ARRAY', async () => {
|
describe('WATCH_ARRAY', () => {
|
||||||
const spy = vi.fn()
|
describe('watch option', () => {
|
||||||
const vm = new Vue({
|
test('basic usage', async () => {
|
||||||
data() {
|
const spy = vi.fn()
|
||||||
return {
|
const vm = new Vue({
|
||||||
foo: [],
|
data() {
|
||||||
}
|
return {
|
||||||
},
|
foo: [],
|
||||||
watch: {
|
}
|
||||||
foo: spy,
|
},
|
||||||
},
|
watch: {
|
||||||
}) as any
|
foo: spy,
|
||||||
expect(
|
},
|
||||||
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
}) as any
|
||||||
).toHaveBeenWarned()
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).toHaveBeenWarned()
|
||||||
|
|
||||||
expect(spy).not.toHaveBeenCalled()
|
expect(spy).not.toHaveBeenCalled()
|
||||||
vm.foo.push(1)
|
vm.foo.push(1)
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expect(spy).toHaveBeenCalledTimes(1)
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('WATCH_ARRAY with non-array initial value', async () => {
|
test('dynamic depth depending on the value', async () => {
|
||||||
const spy = vi.fn()
|
const spy = vi.fn()
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
foo: null,
|
foo: {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
foo: spy,
|
foo: spy,
|
||||||
},
|
},
|
||||||
}) as any
|
}) as any
|
||||||
expect(
|
|
||||||
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
|
||||||
).not.toHaveBeenWarned()
|
|
||||||
|
|
||||||
expect(spy).not.toHaveBeenCalled()
|
vm.foo.bar = 1
|
||||||
vm.foo = []
|
await nextTick()
|
||||||
await nextTick()
|
expect(
|
||||||
expect(
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
).not.toHaveBeenWarned()
|
||||||
).toHaveBeenWarned()
|
expect(spy).not.toHaveBeenCalled()
|
||||||
expect(spy).toHaveBeenCalledTimes(1)
|
|
||||||
vm.foo.push(1)
|
vm.foo = []
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expect(spy).toHaveBeenCalledTimes(2)
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).toHaveBeenWarned()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
vm.foo.push({})
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
vm.foo[0].bar = 2
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
vm.foo = {}
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(3)
|
||||||
|
|
||||||
|
vm.foo.bar = 3
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(3)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('deep: true', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const vm = new Vue({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
foo: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
foo: {
|
||||||
|
handler: spy,
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}) as any
|
||||||
|
|
||||||
|
vm.foo.bar = 1
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
vm.foo = []
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
vm.foo.push({})
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(3)
|
||||||
|
|
||||||
|
vm.foo[0].bar = 2
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(4)
|
||||||
|
|
||||||
|
vm.foo = {}
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(5)
|
||||||
|
|
||||||
|
vm.foo.bar = 3
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(6)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).not.toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('checks correct instance for compat config', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const vm = new Vue({
|
||||||
|
compatConfig: {
|
||||||
|
WATCH_ARRAY: false,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
foo: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
foo: spy,
|
||||||
|
},
|
||||||
|
}) as any
|
||||||
|
|
||||||
|
vm.foo.push(1)
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
const orig = vm.foo
|
||||||
|
vm.foo = []
|
||||||
|
vm.foo = orig
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
vm.foo = []
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).not.toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('passing other options', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const vm = new Vue({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
foo: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
foo: {
|
||||||
|
handler: spy,
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}) as any
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).toHaveBeenWarned()
|
||||||
|
|
||||||
|
vm.foo.push({})
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
vm.foo[0].bar = 1
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('$watch()', () => {
|
||||||
|
test('basic usage', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const vm = new Vue({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
foo: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}) as any
|
||||||
|
vm.$watch('foo', spy)
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).toHaveBeenWarned()
|
||||||
|
|
||||||
|
expect(spy).not.toHaveBeenCalled()
|
||||||
|
vm.foo.push(1)
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('dynamic depth depending on the value', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const vm = new Vue({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
foo: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}) as any
|
||||||
|
vm.$watch('foo', spy)
|
||||||
|
|
||||||
|
vm.foo.bar = 1
|
||||||
|
await nextTick()
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).not.toHaveBeenWarned()
|
||||||
|
expect(spy).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
vm.foo = []
|
||||||
|
await nextTick()
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).toHaveBeenWarned()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
vm.foo.push({})
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
vm.foo[0].bar = 2
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
vm.foo = {}
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(3)
|
||||||
|
|
||||||
|
vm.foo.bar = 3
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(3)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('deep: true', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const vm = new Vue({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
foo: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}) as any
|
||||||
|
vm.$watch('foo', spy, { deep: true })
|
||||||
|
|
||||||
|
vm.foo.bar = 1
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
vm.foo = []
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
vm.foo.push({})
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(3)
|
||||||
|
|
||||||
|
vm.foo[0].bar = 2
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(4)
|
||||||
|
|
||||||
|
vm.foo = {}
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(5)
|
||||||
|
|
||||||
|
vm.foo.bar = 3
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(6)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).not.toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('not deep for a function getter', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const vm = new Vue({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
foo: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}) as any
|
||||||
|
vm.$watch(() => vm.foo, spy)
|
||||||
|
|
||||||
|
expect(spy).not.toHaveBeenCalled()
|
||||||
|
vm.foo.push(1)
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).not.toHaveBeenCalled()
|
||||||
|
vm.foo = []
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
vm.foo.push(1)
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).not.toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('checks correct instance for compat config', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const vm = new Vue({
|
||||||
|
compatConfig: {
|
||||||
|
WATCH_ARRAY: false,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
foo: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}) as any
|
||||||
|
vm.$watch('foo', spy)
|
||||||
|
|
||||||
|
vm.foo.push(1)
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
const orig = vm.foo
|
||||||
|
vm.foo = []
|
||||||
|
vm.foo = orig
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
vm.foo = []
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).not.toHaveBeenWarned()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('passing other options', async () => {
|
||||||
|
const spy = vi.fn()
|
||||||
|
const vm = new Vue({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
foo: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}) as any
|
||||||
|
|
||||||
|
vm.$watch('foo', {
|
||||||
|
handler: spy,
|
||||||
|
immediate: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(
|
||||||
|
deprecationData[DeprecationTypes.WATCH_ARRAY].message,
|
||||||
|
).toHaveBeenWarned()
|
||||||
|
|
||||||
|
vm.foo.push({})
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
vm.foo[0].bar = 1
|
||||||
|
await nextTick()
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('PROPS_DEFAULT_THIS', () => {
|
test('PROPS_DEFAULT_THIS', () => {
|
||||||
|
|
Loading…
Reference in New Issue