vue3-yuanma/packages/runtime-core/src/componentSlots.ts

60 lines
1.8 KiB
TypeScript
Raw Normal View History

2019-05-31 18:07:43 +08:00
import { ComponentInstance } from './component'
import { VNode, NormalizedChildren, normalizeVNode, VNodeChild } from './vnode'
import { isArray, isFunction } from '@vue/shared'
2019-08-22 23:12:37 +08:00
import { ShapeFlags } from './shapeFlags'
2019-05-31 18:07:43 +08:00
export type Slot = (...args: any[]) => VNode[]
export type Slots = Readonly<{
[name: string]: Slot
}>
export type RawSlots = {
[name: string]: unknown
}
const normalizeSlotValue = (value: unknown): VNode[] =>
isArray(value)
? value.map(normalizeVNode)
: [normalizeVNode(value as VNodeChild)]
const normalizeSlot = (rawSlot: Function): Slot => (props: any) =>
normalizeSlotValue(rawSlot(props))
export function resolveSlots(
instance: ComponentInstance,
children: NormalizedChildren
) {
let slots: Slots | void
2019-08-22 23:12:37 +08:00
if (instance.vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {
2019-05-31 18:07:43 +08:00
if ((children as any)._normalized) {
2019-06-03 19:59:15 +08:00
// pre-normalized slots object generated by compiler
2019-05-31 18:07:43 +08:00
slots = children as Slots
} else {
slots = {}
for (const key in children as RawSlots) {
let value = (children as RawSlots)[key]
2019-05-31 18:07:43 +08:00
if (isFunction(value)) {
;(slots as any)[key] = normalizeSlot(value)
} else {
if (__DEV__) {
// TODO show tip on using functions
console.log('use function slots!')
}
value = normalizeSlotValue(value)
;(slots as any)[key] = () => value
}
}
}
} else if (children !== null) {
// non slot object children (direct value) passed to a component
2019-05-31 18:07:43 +08:00
if (__DEV__) {
// TODO show tip on using functions
console.log('use function slots!')
}
const normalized = normalizeSlotValue(children)
slots = { default: () => normalized }
}
if (slots !== void 0) {
instance.slots = slots
}
}