]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: data option compat
authorEvan You <yyx990803@gmail.com>
Tue, 6 Apr 2021 13:31:47 +0000 (09:31 -0400)
committerEvan You <yyx990803@gmail.com>
Wed, 7 Apr 2021 20:19:24 +0000 (16:19 -0400)
packages/runtime-core/src/compat/data.ts [new file with mode: 0644]
packages/runtime-core/src/compat/deprecations.ts
packages/runtime-core/src/compat/global.ts
packages/runtime-core/src/componentOptions.ts
packages/runtime-core/src/warning.ts

diff --git a/packages/runtime-core/src/compat/data.ts b/packages/runtime-core/src/compat/data.ts
new file mode 100644 (file)
index 0000000..dbe66a8
--- /dev/null
@@ -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
+    }
+  }
+}
index 749c04b8fc01e89b61b353326b15f1b5f0c997cd..76a6d358a1568248739dd758ee23d6d1f8f493c0 100644 (file)
@@ -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, DeprecationData> = {
   [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}` : ``}`
   )
 }
index dac2719c2f7cdbe0c44f21f7f8b8a3ceb8bd6a8a..aa59de6e741bd41e1d0049b0723557e8950f9c94 100644 (file)
@@ -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]
           },
index 7b4081afecc9e7d944f9043b13e3596b7c63636e..06fd0d50f772fed53e5fbd9cc733b38ddfe22e03 100644 (file)
@@ -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)
+    }
   }
 }
 
index ad58778e91326cf6aaa46ae351eabfc4e5662bab..ad31bc817cdb92c9c36ccb2324f61c4b977e311f 100644 (file)
@@ -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 []