feat: support initializers in mixins
This commit is contained in:
parent
456ee13ec9
commit
7ce16ea8d6
@ -137,8 +137,16 @@ class InternalComponent implements PublicInstanceMethods {
|
||||
_isVue: boolean = true
|
||||
_inactiveRoot: boolean = false
|
||||
|
||||
constructor() {
|
||||
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
|
||||
|
@ -6,12 +6,21 @@ const internalRE = /^_|^\$/
|
||||
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
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
mergeComponentOptions
|
||||
} from '../componentOptions'
|
||||
import { normalizePropsOptions } from '../componentProps'
|
||||
import { extractInitializers } from '../componentState'
|
||||
import { isFunction } from '@vue/shared'
|
||||
|
||||
interface ComponentConstructor<This = Component> {
|
||||
@ -36,14 +37,25 @@ export function mixins(...args: any[]): any {
|
||||
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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user