diff --git a/packages/core/src/componentOptions.ts b/packages/core/src/componentOptions.ts
index ff3545f2..77fbb515 100644
--- a/packages/core/src/componentOptions.ts
+++ b/packages/core/src/componentOptions.ts
@@ -15,13 +15,17 @@ export interface ComponentClassOptions
{
computed?: ComponentComputedOptions
watch?: ComponentWatchOptions
displayName?: string
+ fromOptions?: boolean
}
export interface ComponentOptions<
P = {},
D = {},
This = ComponentInstance
-> extends ComponentClassOptions
, APIMethods
, LifecycleMethods {
+>
+ extends ComponentClassOptions
,
+ Partial>,
+ Partial {
// TODO other options
readonly [key: string]: any
}
@@ -161,10 +165,7 @@ export function mergeComponentOptions(to: any, from: any): ComponentOptions {
if (isFunction(value) && isFunction(existing)) {
if (key === 'data') {
// for data we need to merge the returned value
- // TODO: backwards compat requires recursive merge
- res[key] = function() {
- return Object.assign(existing.call(this), value.call(this))
- }
+ res[key] = mergeDataFn(existing, value)
} else if (/^render|^errorCaptured/.test(key)) {
// render, renderTracked, renderTriggered & errorCaptured
// are never merged
@@ -186,3 +187,11 @@ export function mergeComponentOptions(to: any, from: any): ComponentOptions {
}
return res
}
+
+export function mergeDataFn(a: Function, b: Function): Function {
+ // TODO: backwards compat requires recursive merge,
+ // but maybe we should just warn if we detect clashing keys
+ return function() {
+ return Object.assign(a.call(this), b.call(this))
+ }
+}
diff --git a/packages/core/src/componentState.ts b/packages/core/src/componentState.ts
index 9a04b02e..8d838dbe 100644
--- a/packages/core/src/componentState.ts
+++ b/packages/core/src/componentState.ts
@@ -2,10 +2,15 @@ import { ComponentInstance } from './component'
import { observable } from '@vue/observer'
import { isReservedKey } from '@vue/shared'
-export function initializeState(instance: ComponentInstance) {
+export function initializeState(
+ instance: ComponentInstance,
+ shouldExtractInitializers: boolean
+) {
const { data } = instance.$options
const rawData = (instance._rawData = (data ? data.call(instance) : {}) as any)
- extractInitializers(instance, rawData)
+ if (shouldExtractInitializers) {
+ extractInitializers(instance, rawData)
+ }
instance.$data = observable(rawData || {})
}
diff --git a/packages/core/src/componentUtils.ts b/packages/core/src/componentUtils.ts
index cad9bb75..54154a3c 100644
--- a/packages/core/src/componentUtils.ts
+++ b/packages/core/src/componentUtils.ts
@@ -45,7 +45,7 @@ export function createComponentInstance(
$proxy,
$options: { created, computed, watch }
} = instance
- initializeState(instance)
+ initializeState(instance, !Component.fromOptions)
initializeComputed(instance, computed)
initializeWatch(instance, watch)
instance.$slots = currentVNode.slots || EMPTY_OBJ
@@ -104,7 +104,7 @@ export function initializeComponentInstance(instance: ComponentInstance) {
export function renderInstanceRoot(instance: ComponentInstance): VNode {
let vnode
try {
- vnode = instance.$options.render.call(
+ vnode = instance.render.call(
instance.$proxy,
instance.$props,
instance.$slots,
@@ -209,6 +209,8 @@ export function createComponentClassFromOptions(
): ComponentClass {
class AnonymousComponent extends Component {
static options = options
+ // indicate this component was created from options
+ static fromOptions = true
}
const proto = AnonymousComponent.prototype as any
for (const key in options) {
diff --git a/packages/core/src/optional/mixins.ts b/packages/core/src/optional/mixins.ts
index cf2b2c09..35fe31ea 100644
--- a/packages/core/src/optional/mixins.ts
+++ b/packages/core/src/optional/mixins.ts
@@ -3,7 +3,8 @@ import { createComponentClassFromOptions } from '../componentUtils'
import {
ComponentOptions,
resolveComponentOptionsFromClass,
- mergeComponentOptions
+ mergeComponentOptions,
+ mergeDataFn
} from '../componentOptions'
import { normalizePropsOptions } from '../componentProps'
import { extractInitializers } from '../componentState'
@@ -47,11 +48,7 @@ export function mixins(...args: any[]): any {
return extractInitializers(new Class(this.$props))
}
const { data } = mixin
- mixin.data = data
- ? function() {
- return Object.assign(data.call(this), extractData.call(this))
- }
- : extractData
+ mixin.data = data ? mergeDataFn(data, extractData) : extractData
} else {
mixin.props = normalizePropsOptions(mixin.props)
}