vue-facing-decorator
Version:
Vue typescript class and decorator based component.
74 lines (68 loc) • 2.62 kB
text/typescript
import type { Cons } from '../component'
import type { OptionBuilder } from '../optionBuilder'
import { obtainSlot, toComponentReverse, excludeNames, getValidNames, optionNullableMemberDecorator } from '../utils'
export const HookNames: ReadonlyArray<string> = [
"beforeCreate",
"created",
"beforeMount",
"mounted",
"beforeUpdate",
"updated",
"activated",
"deactivated",
"beforeDestroy",
"beforeUnmount",
"destroyed",
"unmounted",
"renderTracked",
"renderTriggered",
"errorCaptured",
"serverPrefetch",
"render"
] as const
export type HookConfig = null
export const decorator = optionNullableMemberDecorator(function (proto: any, name: string) {
const slot = obtainSlot(proto)
const map = slot.obtainMap('hooks');
map.set(name, null)
})
export function build(cons: Cons, optionBuilder: OptionBuilder) {
const slot = obtainSlot(cons.prototype)
const protoArr = toComponentReverse(cons.prototype)
const map = slot.obtainMap('hooks')
optionBuilder.hooks ??= {}
optionBuilder.methods ??= {}
const HookFunctions: Record<string, Function> = {}
const MethodFunctions: Record<string, Function> = {}
protoArr.forEach(proto => {
let names = getValidNames(proto, (des, name) => {
return typeof des.value === 'function' && name !== 'constructor'
})
names = excludeNames(names, slot, (mapName) => {
//include these names:
//watch, user may call watch method directly
//hooks, user may call hook method directly
//emits, user may have a method name which is same as one of event names
return !['watch', 'hooks', 'emits', 'provide'].includes(mapName)
});
names.forEach(name => {
if (HookNames.includes(name) || map.has(name)) {
HookFunctions[name] = proto[name]
} else {
MethodFunctions[name] = proto[name]
}
})
})
Object.assign(optionBuilder.methods, MethodFunctions)
const beforeCreateCallbacks = [...optionBuilder.beforeCreateCallbacks ?? []]
if (beforeCreateCallbacks && beforeCreateCallbacks.length > 0) {
const oldBeforeCreateCallback = HookFunctions['beforeCreate']
HookFunctions['beforeCreate'] = function () {
beforeCreateCallbacks.forEach(callback => callback.apply(this, arguments))
if (oldBeforeCreateCallback) {
oldBeforeCreateCallback.apply(this, arguments)
}
}
}
Object.assign(optionBuilder.hooks, HookFunctions)
}