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
|
_isVue: boolean = true
|
||||||
_inactiveRoot: boolean = false
|
_inactiveRoot: boolean = false
|
||||||
|
|
||||||
constructor() {
|
constructor(props?: object) {
|
||||||
|
if (props === void 0) {
|
||||||
initializeComponentInstance(this as any)
|
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
|
// to be set by renderer during mount
|
||||||
|
@ -6,12 +6,21 @@ const internalRE = /^_|^\$/
|
|||||||
export function initializeState(instance: ComponentInstance) {
|
export function initializeState(instance: ComponentInstance) {
|
||||||
const { data } = instance.$options
|
const { data } = instance.$options
|
||||||
const rawData = (instance._rawData = (data ? data.call(instance) : {}) as any)
|
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)
|
const keys = Object.keys(instance)
|
||||||
for (let i = 0; i < keys.length; i++) {
|
for (let i = 0; i < keys.length; i++) {
|
||||||
const key = keys[i]
|
const key = keys[i]
|
||||||
if (!internalRE.test(key)) {
|
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
|
mergeComponentOptions
|
||||||
} from '../componentOptions'
|
} from '../componentOptions'
|
||||||
import { normalizePropsOptions } from '../componentProps'
|
import { normalizePropsOptions } from '../componentProps'
|
||||||
|
import { extractInitializers } from '../componentState'
|
||||||
import { isFunction } from '@vue/shared'
|
import { isFunction } from '@vue/shared'
|
||||||
|
|
||||||
interface ComponentConstructor<This = Component> {
|
interface ComponentConstructor<This = Component> {
|
||||||
@ -36,14 +37,25 @@ export function mixins(...args: any[]): any {
|
|||||||
let options: ComponentOptions = {}
|
let options: ComponentOptions = {}
|
||||||
args.forEach(mixin => {
|
args.forEach(mixin => {
|
||||||
if (isFunction(mixin)) {
|
if (isFunction(mixin)) {
|
||||||
options = mergeComponentOptions(
|
const Class = mixin
|
||||||
options,
|
mixin = resolveComponentOptionsFromClass(Class)
|
||||||
resolveComponentOptionsFromClass(mixin)
|
// 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 {
|
} else {
|
||||||
mixin.props = normalizePropsOptions(mixin.props)
|
mixin.props = normalizePropsOptions(mixin.props)
|
||||||
options = mergeComponentOptions(options, mixin)
|
|
||||||
}
|
}
|
||||||
|
options = mergeComponentOptions(options, mixin)
|
||||||
})
|
})
|
||||||
return createComponentClassFromOptions(options)
|
return createComponentClassFromOptions(options)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user