From d0da0028f2c3ebe88fe0c9a1271e5ae624092a2c Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 6 Apr 2021 09:31:47 -0400 Subject: [PATCH] wip: data option compat --- packages/runtime-core/src/compat/data.ts | 15 +++++++++ .../runtime-core/src/compat/deprecations.ts | 32 +++++++++++++++---- packages/runtime-core/src/compat/global.ts | 7 +++- packages/runtime-core/src/componentOptions.ts | 7 +++- packages/runtime-core/src/warning.ts | 2 +- 5 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 packages/runtime-core/src/compat/data.ts diff --git a/packages/runtime-core/src/compat/data.ts b/packages/runtime-core/src/compat/data.ts new file mode 100644 index 000000000..dbe66a8de --- /dev/null +++ b/packages/runtime-core/src/compat/data.ts @@ -0,0 +1,15 @@ +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 + } + } +} diff --git a/packages/runtime-core/src/compat/deprecations.ts b/packages/runtime-core/src/compat/deprecations.ts index 749c04b8f..76a6d358a 100644 --- a/packages/runtime-core/src/compat/deprecations.ts +++ b/packages/runtime-core/src/compat/deprecations.ts @@ -1,4 +1,5 @@ import { isRuntimeOnly } from '../component' +import { warn } from '../warning' export const enum DeprecationTypes { CONFIG_SILENT, @@ -16,11 +17,14 @@ export const enum DeprecationTypes { 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 } @@ -120,17 +124,31 @@ const deprecations: Record = { [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}` : ``}` ) } diff --git a/packages/runtime-core/src/compat/global.ts b/packages/runtime-core/src/compat/global.ts index dac2719c2..aa59de6e7 100644 --- a/packages/runtime-core/src/compat/global.ts +++ b/packages/runtime-core/src/compat/global.ts @@ -162,9 +162,14 @@ export function createCompatVue( 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] }, diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 7b4081afe..06fd0d50f 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -65,6 +65,7 @@ import { warn } from './warning' import { VNodeChild } from './vnode' import { callWithAsyncErrorHandling } from './errorHandling' import { UnionToIntersection } from './helpers/typeUtils' +import { deepMergeData } from './compat/data' /** * Interface for declaring custom options. @@ -904,7 +905,11 @@ function resolveData( 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) + } } } diff --git a/packages/runtime-core/src/warning.ts b/packages/runtime-core/src/warning.ts index ad58778e9..ad31bc817 100644 --- a/packages/runtime-core/src/warning.ts +++ b/packages/runtime-core/src/warning.ts @@ -71,7 +71,7 @@ export function warn(msg: string, ...args: any[]) { resetTracking() } -function getComponentTrace(): ComponentTraceStack { +export function getComponentTrace(): ComponentTraceStack { let currentVNode: VNode | null = stack[stack.length - 1] if (!currentVNode) { return []