--- /dev/null
+import { isPlainObject } from '@vue/shared'
+import { DeprecationTypes, warnDeprecation } from './deprecations'
+
+export function deepMergeData(to: any, from: any) {
+ for (const key in from) {
+ const toVal = to[key]
+ const fromVal = from[key]
+ if (key in to && isPlainObject(toVal) && isPlainObject(fromVal)) {
+ __DEV__ && warnDeprecation(DeprecationTypes.OPTIONS_DATA_MERGE, key)
+ deepMergeData(toVal, fromVal)
+ } else {
+ to[key] = fromVal
+ }
+ }
+}
import { isRuntimeOnly } from '../component'
+import { warn } from '../warning'
export const enum DeprecationTypes {
CONFIG_SILENT,
INSTANCE_SET,
INSTANCE_DELETE,
INSTANCE_MOUNT,
- INSTANCE_DESTROY
+ INSTANCE_DESTROY,
+
+ OPTIONS_DATA_FN,
+ OPTIONS_DATA_MERGE
}
type DeprecationData = {
- message: string | (() => string)
+ message: string | ((...args: any[]) => string)
link?: string
}
[DeprecationTypes.INSTANCE_DESTROY]: {
message: `vm.$destroy() has been removed. Use app.unmount() instead.`,
link: `https://v3.vuejs.org/api/application-api.html#unmount`
+ },
+
+ [DeprecationTypes.OPTIONS_DATA_FN]: {
+ message:
+ `The "data" option can no longer be a plain object. ` +
+ `Always use a function.`,
+ link: `https://v3.vuejs.org/guide/migration/data-option.html`
+ },
+
+ [DeprecationTypes.OPTIONS_DATA_MERGE]: {
+ message: (key: string) =>
+ `Detected conflicting key "${key}" when merging "data" option values. ` +
+ `In Vue 3, data keys are merged shallowly and will override one another.`,
+ link: `https://v3.vuejs.org/guide/migration/data-option.html#mixin-merge-behavior-change`
}
}
-export function warnDeprecation(key: DeprecationTypes) {
+export function warnDeprecation(key: DeprecationTypes, ...args: any[]) {
if (!__COMPAT__ || !__DEV__) {
return
}
const { message, link } = deprecations[key]
- console.warn(
- `[Vue Deprecation]: ${typeof message === 'function' ? message() : message}${
- link ? `\nFor more details, see ${link}` : ``
- }`
+ warn(
+ `[DEPRECATION] ${
+ typeof message === 'function' ? message(...args) : message
+ }${link ? `\nFor more details, see ${link}` : ``}`
)
}
if (!inlineOptions) {
return createCompatApp(options, SubVue)
} else {
+ const { el, data } = inlineOptions
+ if (data && !isFunction(data)) {
+ __DEV__ && warnDeprecation(DeprecationTypes.OPTIONS_DATA_FN)
+ inlineOptions.data = () => data
+ }
return createCompatApp(
{
- el: inlineOptions.el,
+ el,
extends: options,
mixins: [inlineOptions]
},
import { VNodeChild } from './vnode'
import { callWithAsyncErrorHandling } from './errorHandling'
import { UnionToIntersection } from './helpers/typeUtils'
+import { deepMergeData } from './compat/data'
/**
* Interface for declaring custom options.
instance.data = reactive(data)
} else {
// existing data: this is a mixin or extends.
- extend(instance.data, data)
+ if (__COMPAT__) {
+ deepMergeData(instance.data, data)
+ } else {
+ extend(instance.data, data)
+ }
}
}