_isVue: boolean = true
_inactiveRoot: boolean = false
- constructor() {
- initializeComponentInstance(this as any)
+ constructor(props?: object) {
+ if (props === void 0) {
+ initializeComponentInstance(this as any)
+ } else {
+ // the presence of the props argument indicates that this class is being
+ // instantiated as a mixin, and should expose the props on itself
+ // so that the extended class constructor (and property initializers) can
+ // access $props.
+ this.$props = props
+ }
}
// to be set by renderer during mount
export function initializeState(instance: ComponentInstance) {
const { data } = instance.$options
const rawData = (instance._rawData = (data ? data.call(instance) : {}) as any)
+ extractInitializers(instance, rawData)
+ instance.$data = observable(rawData || {})
+}
+
+// extract properties initialized in a component's constructor
+export function extractInitializers(
+ instance: ComponentInstance,
+ data: any = {}
+): any {
const keys = Object.keys(instance)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
if (!internalRE.test(key)) {
- rawData[key] = (instance as any)[key]
+ data[key] = (instance as any)[key]
}
}
- instance.$data = observable(rawData || {})
+ return data
}
mergeComponentOptions
} from '../componentOptions'
import { normalizePropsOptions } from '../componentProps'
+import { extractInitializers } from '../componentState'
import { isFunction } from '@vue/shared'
interface ComponentConstructor<This = Component> {
let options: ComponentOptions = {}
args.forEach(mixin => {
if (isFunction(mixin)) {
- options = mergeComponentOptions(
- options,
- resolveComponentOptionsFromClass(mixin)
- )
+ const Class = mixin
+ mixin = resolveComponentOptionsFromClass(Class)
+ // in order to extract properties initialized in the mixin's constructor,
+ // we create an instance of it and pass in the actual props - this
+ // short-circuits the normal component initialization and allows us to
+ // relatively-cheaply extract the properties added in the constructor.
+ function extractData() {
+ return extractInitializers(new Class(this.$props))
+ }
+ const { data } = mixin
+ mixin.data = data
+ ? function() {
+ return Object.assign(data.call(this), extractData.call(this))
+ }
+ : extractData
} else {
mixin.props = normalizePropsOptions(mixin.props)
- options = mergeComponentOptions(options, mixin)
}
+ options = mergeComponentOptions(options, mixin)
})
return createComponentClassFromOptions(options)
}