204 lines
4.5 KiB
TypeScript
204 lines
4.5 KiB
TypeScript
|
import {
|
||
|
ComponentInstance,
|
||
|
Data,
|
||
|
ComponentOptions,
|
||
|
ComponentRenderProxy
|
||
|
} from './component'
|
||
|
import {
|
||
|
isFunction,
|
||
|
extend,
|
||
|
isString,
|
||
|
isObject,
|
||
|
isArray,
|
||
|
EMPTY_OBJ
|
||
|
} from '@vue/shared'
|
||
|
import { computed, ComputedOptions } from './apiReactivity'
|
||
|
import { watch } from './apiWatch'
|
||
|
import { provide, inject } from './apiInject'
|
||
|
import {
|
||
|
onBeforeMount,
|
||
|
onMounted,
|
||
|
onBeforeUpdate,
|
||
|
onUpdated,
|
||
|
onErrorCaptured,
|
||
|
onRenderTracked,
|
||
|
onBeforeUnmount,
|
||
|
onUnmounted
|
||
|
} from './apiLifecycle'
|
||
|
import { DebuggerEvent } from '@vue/reactivity'
|
||
|
|
||
|
type LegacyComponent =
|
||
|
| ComponentOptions
|
||
|
| {
|
||
|
new (): ComponentRenderProxy
|
||
|
options: ComponentOptions
|
||
|
}
|
||
|
|
||
|
// TODO type inference for these options
|
||
|
export interface LegacyOptions {
|
||
|
el?: any
|
||
|
|
||
|
// state
|
||
|
data?: Data | (() => Data)
|
||
|
computed?: Record<string, (() => any) | ComputedOptions>
|
||
|
methods?: Record<string, Function>
|
||
|
// TODO watch array
|
||
|
watch?: Record<
|
||
|
string,
|
||
|
| string
|
||
|
| Function
|
||
|
| { handler: Function; deep?: boolean; immediate: boolean }
|
||
|
>
|
||
|
provide?: Data | (() => Data)
|
||
|
inject?:
|
||
|
| string[]
|
||
|
| Record<
|
||
|
string | symbol,
|
||
|
string | symbol | { from: string | symbol; default: any }
|
||
|
>
|
||
|
|
||
|
// composition
|
||
|
mixins?: LegacyComponent[]
|
||
|
extends?: LegacyComponent
|
||
|
|
||
|
// lifecycle
|
||
|
beforeCreate?(): void
|
||
|
created?(): void
|
||
|
beforeMount?(): void
|
||
|
mounted?(): void
|
||
|
beforeUpdate?(): void
|
||
|
updated?(): void
|
||
|
activated?(): void
|
||
|
decativated?(): void
|
||
|
beforeDestroy?(): void
|
||
|
destroyed?(): void
|
||
|
renderTracked?(e: DebuggerEvent): void
|
||
|
renderTriggered?(e: DebuggerEvent): void
|
||
|
errorCaptured?(): boolean
|
||
|
}
|
||
|
|
||
|
export function processOptions(instance: ComponentInstance) {
|
||
|
const data =
|
||
|
instance.data === EMPTY_OBJ ? (instance.data = {}) : instance.data
|
||
|
const ctx = instance.renderProxy as any
|
||
|
const {
|
||
|
data: dataOptions,
|
||
|
computed: computedOptions,
|
||
|
methods,
|
||
|
watch: watchOptions,
|
||
|
provide: provideOptions,
|
||
|
inject: injectOptions,
|
||
|
// beforeCreate is handled separately
|
||
|
created,
|
||
|
beforeMount,
|
||
|
mounted,
|
||
|
beforeUpdate,
|
||
|
updated,
|
||
|
// TODO activated
|
||
|
// TODO decativated
|
||
|
beforeDestroy,
|
||
|
destroyed,
|
||
|
renderTracked,
|
||
|
renderTriggered,
|
||
|
errorCaptured
|
||
|
} = instance.type as ComponentOptions
|
||
|
|
||
|
if (dataOptions) {
|
||
|
extend(data, isFunction(dataOptions) ? dataOptions.call(ctx) : dataOptions)
|
||
|
}
|
||
|
|
||
|
if (computedOptions) {
|
||
|
for (const key in computedOptions) {
|
||
|
data[key] = computed(computedOptions[key] as any)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (methods) {
|
||
|
for (const key in methods) {
|
||
|
data[key] = methods[key].bind(ctx)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (watchOptions) {
|
||
|
for (const key in watchOptions) {
|
||
|
const raw = watchOptions[key]
|
||
|
const getter = () => ctx[key]
|
||
|
if (isString(raw)) {
|
||
|
const handler = data[key]
|
||
|
if (isFunction(handler)) {
|
||
|
watch(getter, handler.bind(ctx))
|
||
|
} else if (__DEV__) {
|
||
|
// TODO warn invalid watch handler path
|
||
|
}
|
||
|
} else if (isFunction(raw)) {
|
||
|
watch(getter, raw.bind(ctx))
|
||
|
} else if (isObject(raw)) {
|
||
|
watch(getter, raw.handler.bind(ctx), {
|
||
|
deep: !!raw.deep,
|
||
|
lazy: !raw.immediate
|
||
|
})
|
||
|
} else if (__DEV__) {
|
||
|
// TODO warn invalid watch options
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (provideOptions) {
|
||
|
const provides = isFunction(provideOptions)
|
||
|
? provideOptions.call(ctx)
|
||
|
: provideOptions
|
||
|
for (const key in provides) {
|
||
|
provide(key, provides[key])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (injectOptions) {
|
||
|
if (isArray(injectOptions)) {
|
||
|
for (let i = 0; i < injectOptions.length; i++) {
|
||
|
const key = injectOptions[i]
|
||
|
data[key] = inject(key)
|
||
|
}
|
||
|
} else {
|
||
|
for (const key in injectOptions) {
|
||
|
const opt = injectOptions[key]
|
||
|
if (isObject(opt)) {
|
||
|
data[key] = inject(opt.from, opt.default)
|
||
|
} else {
|
||
|
data[key] = inject(opt)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (created) {
|
||
|
created.call(ctx)
|
||
|
}
|
||
|
if (beforeMount) {
|
||
|
onBeforeMount(beforeMount.bind(ctx))
|
||
|
}
|
||
|
if (mounted) {
|
||
|
onMounted(mounted.bind(ctx))
|
||
|
}
|
||
|
if (beforeUpdate) {
|
||
|
onBeforeUpdate(beforeUpdate.bind(ctx))
|
||
|
}
|
||
|
if (updated) {
|
||
|
onUpdated(updated.bind(ctx))
|
||
|
}
|
||
|
if (errorCaptured) {
|
||
|
onErrorCaptured(errorCaptured.bind(ctx))
|
||
|
}
|
||
|
if (renderTracked) {
|
||
|
onRenderTracked(renderTracked.bind(ctx))
|
||
|
}
|
||
|
if (renderTriggered) {
|
||
|
onRenderTracked(renderTriggered.bind(ctx))
|
||
|
}
|
||
|
if (beforeDestroy) {
|
||
|
onBeforeUnmount(beforeDestroy.bind(ctx))
|
||
|
}
|
||
|
if (destroyed) {
|
||
|
onUnmounted(destroyed.bind(ctx))
|
||
|
}
|
||
|
}
|