2023-12-10 01:33:18 +08:00
|
|
|
import {
|
2024-12-04 13:50:54 +08:00
|
|
|
type ComponentInternalOptions,
|
2023-12-10 01:33:18 +08:00
|
|
|
type ComponentPropsOptions,
|
2024-12-04 13:50:54 +08:00
|
|
|
EffectScope,
|
2024-12-04 15:07:40 +08:00
|
|
|
type EmitFn,
|
2024-02-04 21:18:57 +08:00
|
|
|
type EmitsOptions,
|
2024-12-04 13:50:54 +08:00
|
|
|
type GenericAppContext,
|
|
|
|
type GenericComponentInstance,
|
|
|
|
type LifecycleHook,
|
|
|
|
type NormalizedPropsOptions,
|
2024-02-04 21:18:57 +08:00
|
|
|
type ObjectEmitsOptions,
|
2024-12-06 01:19:20 +08:00
|
|
|
type SuspenseBoundary,
|
2024-12-05 23:13:24 +08:00
|
|
|
currentInstance,
|
2024-12-04 13:50:54 +08:00
|
|
|
nextUid,
|
|
|
|
popWarningContext,
|
|
|
|
pushWarningContext,
|
2024-12-08 17:20:34 +08:00
|
|
|
registerHMR,
|
2024-12-05 23:13:24 +08:00
|
|
|
setCurrentInstance,
|
2024-12-04 15:07:40 +08:00
|
|
|
warn,
|
2024-12-04 14:22:26 +08:00
|
|
|
} from '@vue/runtime-dom'
|
2024-12-04 15:07:40 +08:00
|
|
|
import { type Block, isBlock } from './block'
|
2024-12-06 11:12:54 +08:00
|
|
|
import { pauseTracking, proxyRefs, resetTracking } from '@vue/reactivity'
|
2024-12-08 21:22:51 +08:00
|
|
|
import { EMPTY_OBJ, invokeArrayFns, isFunction, isString } from '@vue/shared'
|
2024-05-29 01:43:47 +08:00
|
|
|
import {
|
2024-12-04 13:50:54 +08:00
|
|
|
type RawProps,
|
2024-12-04 23:02:15 +08:00
|
|
|
getPropsProxyHandlers,
|
2024-12-05 16:14:24 +08:00
|
|
|
hasFallthroughAttrs,
|
2024-12-04 23:02:15 +08:00
|
|
|
normalizePropsOptions,
|
2024-12-06 11:10:35 +08:00
|
|
|
resolveDynamicProps,
|
2024-12-05 16:14:24 +08:00
|
|
|
setupPropsValidation,
|
2024-12-04 13:50:54 +08:00
|
|
|
} from './componentProps'
|
|
|
|
import { renderEffect } from './renderEffect'
|
2024-12-04 23:50:59 +08:00
|
|
|
import { emit, normalizeEmitsOptions } from './componentEmits'
|
2024-12-06 11:10:35 +08:00
|
|
|
import { setStyle } from './dom/style'
|
|
|
|
import { setClass, setDynamicProp } from './dom/prop'
|
2024-12-06 21:08:24 +08:00
|
|
|
import {
|
|
|
|
type RawSlots,
|
2024-12-08 16:12:08 +08:00
|
|
|
type Slot,
|
2024-12-06 22:45:45 +08:00
|
|
|
type StaticSlots,
|
2024-12-06 23:10:41 +08:00
|
|
|
dynamicSlotsProxyHandlers,
|
2024-12-07 15:12:32 +08:00
|
|
|
getSlot,
|
2024-12-06 21:08:24 +08:00
|
|
|
} from './componentSlots'
|
2024-12-08 21:22:51 +08:00
|
|
|
import { insert, remove } from './dom/node'
|
|
|
|
import { hmrReload, hmrRerender } from './hmr'
|
2023-12-10 01:33:18 +08:00
|
|
|
|
2024-12-05 23:13:24 +08:00
|
|
|
export { currentInstance } from '@vue/runtime-dom'
|
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
export type VaporComponent = FunctionalVaporComponent | ObjectVaporComponent
|
2024-12-02 20:35:45 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
export type VaporSetupFn = (
|
2024-12-02 09:36:49 +08:00
|
|
|
props: any,
|
|
|
|
ctx: SetupContext,
|
2024-12-04 13:50:54 +08:00
|
|
|
) => Block | Record<string, any> | undefined
|
2024-12-02 20:35:45 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
export type FunctionalVaporComponent = VaporSetupFn &
|
|
|
|
Omit<ObjectVaporComponent, 'setup'> & {
|
2024-04-28 18:43:16 +08:00
|
|
|
displayName?: string
|
2024-12-02 20:35:45 +08:00
|
|
|
} & SharedInternalOptions
|
2024-02-14 14:43:18 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
export interface ObjectVaporComponent
|
2024-12-02 20:35:45 +08:00
|
|
|
extends ComponentInternalOptions,
|
|
|
|
SharedInternalOptions {
|
2024-12-04 13:50:54 +08:00
|
|
|
setup?: VaporSetupFn
|
2024-03-19 00:24:58 +08:00
|
|
|
inheritAttrs?: boolean
|
2024-04-28 18:43:16 +08:00
|
|
|
props?: ComponentPropsOptions
|
2024-02-14 14:43:18 +08:00
|
|
|
emits?: EmitsOptions
|
2024-12-08 16:12:08 +08:00
|
|
|
render?(
|
|
|
|
ctx: any,
|
|
|
|
props?: any,
|
|
|
|
emit?: EmitFn,
|
|
|
|
attrs?: any,
|
|
|
|
slots?: Record<string, Slot>,
|
|
|
|
): Block
|
2024-04-28 18:43:16 +08:00
|
|
|
|
|
|
|
name?: string
|
2024-02-14 14:43:18 +08:00
|
|
|
vapor?: boolean
|
2023-12-06 14:59:11 +08:00
|
|
|
}
|
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
interface SharedInternalOptions {
|
2024-04-28 18:43:16 +08:00
|
|
|
/**
|
2024-12-04 13:50:54 +08:00
|
|
|
* Cached normalized props options.
|
|
|
|
* In vapor mode there are no mixins so normalized options can be cached
|
|
|
|
* directly on the component
|
2024-04-28 18:43:16 +08:00
|
|
|
*/
|
2024-12-04 13:50:54 +08:00
|
|
|
__propsOptions?: NormalizedPropsOptions
|
2024-04-28 18:43:16 +08:00
|
|
|
/**
|
2024-12-04 13:50:54 +08:00
|
|
|
* Cached normalized props proxy handlers.
|
2024-04-28 18:43:16 +08:00
|
|
|
*/
|
2024-12-04 13:50:54 +08:00
|
|
|
__propsHandlers?: [ProxyHandler<any> | null, ProxyHandler<any>]
|
2024-04-28 18:43:16 +08:00
|
|
|
/**
|
2024-12-04 13:50:54 +08:00
|
|
|
* Cached normalized emits options.
|
2024-04-28 18:43:16 +08:00
|
|
|
*/
|
2024-12-04 13:50:54 +08:00
|
|
|
__emitsOptions?: ObjectEmitsOptions
|
2024-04-28 18:43:16 +08:00
|
|
|
}
|
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
export function createComponent(
|
|
|
|
component: VaporComponent,
|
2024-12-07 15:12:32 +08:00
|
|
|
rawProps?: RawProps | null,
|
|
|
|
rawSlots?: RawSlots | null,
|
2024-12-04 13:50:54 +08:00
|
|
|
isSingleRoot?: boolean,
|
|
|
|
): VaporComponentInstance {
|
|
|
|
// check if we are the single root of the parent
|
|
|
|
// if yes, inject parent attrs as dynamic props source
|
2024-12-05 23:13:24 +08:00
|
|
|
if (
|
|
|
|
isSingleRoot &&
|
|
|
|
isVaporComponent(currentInstance) &&
|
|
|
|
currentInstance.hasFallthrough
|
|
|
|
) {
|
2024-12-04 20:55:10 +08:00
|
|
|
const attrs = currentInstance.attrs
|
2024-12-04 13:50:54 +08:00
|
|
|
if (rawProps) {
|
2024-12-04 20:55:10 +08:00
|
|
|
;(rawProps.$ || (rawProps.$ = [])).push(() => attrs)
|
2024-12-04 13:50:54 +08:00
|
|
|
} else {
|
2024-12-04 20:55:10 +08:00
|
|
|
rawProps = { $: [() => attrs] } as RawProps
|
2024-12-04 13:50:54 +08:00
|
|
|
}
|
|
|
|
}
|
2024-12-01 16:41:51 +08:00
|
|
|
|
2024-12-07 15:12:32 +08:00
|
|
|
const instance = new VaporComponentInstance(component, rawProps, rawSlots)
|
2024-12-05 23:13:24 +08:00
|
|
|
const resetCurrentInstance = setCurrentInstance(instance)
|
2024-12-01 16:41:51 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
pauseTracking()
|
|
|
|
if (__DEV__) {
|
|
|
|
pushWarningContext(instance)
|
|
|
|
}
|
|
|
|
|
|
|
|
const setupFn = isFunction(component) ? component : component.setup
|
2024-12-07 21:43:08 +08:00
|
|
|
const setupResult = setupFn
|
|
|
|
? setupFn(
|
|
|
|
instance.props,
|
|
|
|
// @ts-expect-error
|
2024-12-08 16:12:08 +08:00
|
|
|
setupFn.length > 1 ? new SetupContext(instance) : null,
|
2024-12-07 21:43:08 +08:00
|
|
|
) || EMPTY_OBJ
|
|
|
|
: EMPTY_OBJ
|
2024-12-04 15:07:40 +08:00
|
|
|
|
|
|
|
if (__DEV__ && !isBlock(setupResult)) {
|
|
|
|
if (isFunction(component)) {
|
|
|
|
warn(`Functional vapor component must return a block directly.`)
|
|
|
|
instance.block = []
|
|
|
|
} else if (!component.render) {
|
|
|
|
warn(
|
|
|
|
`Vapor component setup() returned non-block value, and has no render function.`,
|
|
|
|
)
|
|
|
|
instance.block = []
|
|
|
|
} else {
|
2024-12-08 17:20:34 +08:00
|
|
|
instance.devtoolsRawSetupState = setupResult
|
|
|
|
instance.setupState = proxyRefs(setupResult)
|
|
|
|
devRender(instance)
|
|
|
|
|
|
|
|
// HMR
|
|
|
|
registerHMR(instance)
|
|
|
|
instance.hmrRerender = hmrRerender.bind(null, instance)
|
2024-12-08 21:22:51 +08:00
|
|
|
instance.hmrReload = hmrReload.bind(null, instance)
|
2024-12-04 15:07:40 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// in prod result can only be block
|
|
|
|
instance.block = setupResult as Block
|
|
|
|
}
|
2024-12-04 13:50:54 +08:00
|
|
|
|
|
|
|
// single root, inherit attrs
|
|
|
|
if (
|
|
|
|
instance.hasFallthrough &&
|
|
|
|
component.inheritAttrs !== false &&
|
|
|
|
instance.block instanceof Element &&
|
|
|
|
Object.keys(instance.attrs).length
|
|
|
|
) {
|
|
|
|
renderEffect(() => {
|
|
|
|
for (const key in instance.attrs) {
|
|
|
|
setDynamicProp(instance.block as Element, key, instance.attrs[key])
|
|
|
|
}
|
|
|
|
})
|
2024-12-01 16:41:51 +08:00
|
|
|
}
|
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
if (__DEV__) {
|
|
|
|
popWarningContext()
|
|
|
|
}
|
|
|
|
resetTracking()
|
2024-12-05 23:13:24 +08:00
|
|
|
resetCurrentInstance()
|
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
return instance
|
2024-12-01 16:41:51 +08:00
|
|
|
}
|
|
|
|
|
2024-12-08 17:20:34 +08:00
|
|
|
/**
|
|
|
|
* dev only
|
|
|
|
*/
|
|
|
|
export function devRender(instance: VaporComponentInstance): void {
|
|
|
|
instance.block = instance.type.render!.call(
|
|
|
|
null,
|
|
|
|
instance.setupState,
|
|
|
|
instance.props,
|
|
|
|
instance.emit,
|
|
|
|
instance.attrs,
|
|
|
|
instance.slots,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
const emptyContext: GenericAppContext = {
|
|
|
|
app: null as any,
|
|
|
|
config: {},
|
|
|
|
provides: /*@__PURE__*/ Object.create(null),
|
|
|
|
}
|
2024-03-19 00:24:58 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
export class VaporComponentInstance implements GenericComponentInstance {
|
2024-12-05 23:13:24 +08:00
|
|
|
vapor: true
|
2023-11-30 02:11:21 +08:00
|
|
|
uid: number
|
2024-12-04 13:50:54 +08:00
|
|
|
type: VaporComponent
|
|
|
|
parent: GenericComponentInstance | null
|
2024-12-08 21:22:51 +08:00
|
|
|
children: VaporComponentInstance[] // TODO handle vdom children
|
2024-12-04 13:50:54 +08:00
|
|
|
appContext: GenericAppContext
|
2024-03-16 18:54:36 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
block: Block
|
2024-09-19 01:15:17 +08:00
|
|
|
scope: EffectScope
|
2024-12-04 13:50:54 +08:00
|
|
|
props: Record<string, any>
|
|
|
|
attrs: Record<string, any>
|
2024-12-06 22:45:45 +08:00
|
|
|
slots: StaticSlots
|
2024-12-04 13:50:54 +08:00
|
|
|
exposed: Record<string, any> | null
|
2023-12-10 01:33:18 +08:00
|
|
|
|
2024-12-07 15:12:32 +08:00
|
|
|
rawProps: RawProps
|
|
|
|
rawSlots: RawSlots
|
|
|
|
|
2024-12-08 16:12:08 +08:00
|
|
|
emit: EmitFn
|
2024-02-04 21:18:57 +08:00
|
|
|
emitted: Record<string, boolean> | null
|
2024-12-04 13:50:54 +08:00
|
|
|
propsDefaults: Record<string, any> | null
|
2023-11-30 02:11:21 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
// for useTemplateRef()
|
|
|
|
refs: Record<string, any>
|
|
|
|
// for provide / inject
|
|
|
|
provides: Record<string, any>
|
2024-12-06 01:19:20 +08:00
|
|
|
// for useId
|
|
|
|
ids: [string, number, number]
|
|
|
|
// for suspense
|
|
|
|
suspense: SuspenseBoundary | null
|
2024-12-04 13:50:54 +08:00
|
|
|
|
|
|
|
hasFallthrough: boolean
|
2024-03-22 23:28:18 +08:00
|
|
|
|
2024-12-05 23:13:24 +08:00
|
|
|
// lifecycle hooks
|
2024-01-20 20:46:41 +08:00
|
|
|
isMounted: boolean
|
|
|
|
isUnmounted: boolean
|
2024-12-04 13:50:54 +08:00
|
|
|
isDeactivated: boolean
|
2024-12-06 00:55:00 +08:00
|
|
|
isUpdating: boolean
|
2024-12-05 23:13:24 +08:00
|
|
|
|
|
|
|
bc?: LifecycleHook // LifecycleHooks.BEFORE_CREATE
|
|
|
|
c?: LifecycleHook // LifecycleHooks.CREATED
|
|
|
|
bm?: LifecycleHook // LifecycleHooks.BEFORE_MOUNT
|
|
|
|
m?: LifecycleHook // LifecycleHooks.MOUNTED
|
|
|
|
bu?: LifecycleHook // LifecycleHooks.BEFORE_UPDATE
|
|
|
|
u?: LifecycleHook // LifecycleHooks.UPDATED
|
|
|
|
um?: LifecycleHook // LifecycleHooks.BEFORE_UNMOUNT
|
|
|
|
bum?: LifecycleHook // LifecycleHooks.UNMOUNTED
|
|
|
|
da?: LifecycleHook // LifecycleHooks.DEACTIVATED
|
|
|
|
a?: LifecycleHook // LifecycleHooks.ACTIVATED
|
|
|
|
rtg?: LifecycleHook // LifecycleHooks.RENDER_TRACKED
|
|
|
|
rtc?: LifecycleHook // LifecycleHooks.RENDER_TRIGGERED
|
|
|
|
ec?: LifecycleHook // LifecycleHooks.ERROR_CAPTURED
|
|
|
|
sp?: LifecycleHook<() => Promise<unknown>> // LifecycleHooks.SERVER_PREFETCH
|
2024-12-01 16:41:51 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
// dev only
|
2024-12-04 15:07:40 +08:00
|
|
|
setupState?: Record<string, any>
|
2024-12-08 17:20:34 +08:00
|
|
|
devtoolsRawSetupState?: any
|
|
|
|
hmrRerender?: () => void
|
2024-12-08 21:22:51 +08:00
|
|
|
hmrReload?: () => void
|
2024-12-04 13:50:54 +08:00
|
|
|
propsOptions?: NormalizedPropsOptions
|
|
|
|
emitsOptions?: ObjectEmitsOptions | null
|
2023-12-10 01:33:18 +08:00
|
|
|
|
2024-12-07 15:12:32 +08:00
|
|
|
constructor(
|
|
|
|
comp: VaporComponent,
|
|
|
|
rawProps?: RawProps | null,
|
|
|
|
rawSlots?: RawSlots | null,
|
|
|
|
) {
|
2024-12-05 23:13:24 +08:00
|
|
|
this.vapor = true
|
2024-12-04 13:50:54 +08:00
|
|
|
this.uid = nextUid()
|
|
|
|
this.type = comp
|
2024-12-06 01:19:20 +08:00
|
|
|
this.parent = currentInstance // TODO proper parent source when inside vdom instance
|
2024-12-08 21:22:51 +08:00
|
|
|
this.children = []
|
|
|
|
|
|
|
|
if (currentInstance) {
|
|
|
|
if (isVaporComponent(currentInstance)) {
|
|
|
|
currentInstance.children.push(this)
|
|
|
|
}
|
|
|
|
this.appContext = currentInstance.appContext
|
|
|
|
this.provides = currentInstance.provides
|
|
|
|
this.ids = currentInstance.ids
|
|
|
|
} else {
|
|
|
|
this.appContext = emptyContext
|
|
|
|
this.provides = Object.create(this.appContext.provides)
|
|
|
|
this.ids = ['', 0, 0]
|
|
|
|
}
|
2024-12-01 16:41:51 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
this.block = null! // to be set
|
|
|
|
this.scope = new EffectScope(true)
|
2024-03-22 23:28:18 +08:00
|
|
|
|
2024-12-08 16:12:08 +08:00
|
|
|
this.emit = emit.bind(null, this)
|
2024-12-05 23:13:24 +08:00
|
|
|
this.refs = EMPTY_OBJ
|
2024-12-06 01:19:20 +08:00
|
|
|
this.emitted = this.exposed = this.propsDefaults = this.suspense = null
|
2024-12-06 00:55:00 +08:00
|
|
|
this.isMounted =
|
|
|
|
this.isUnmounted =
|
|
|
|
this.isUpdating =
|
|
|
|
this.isDeactivated =
|
|
|
|
false
|
2024-12-04 13:50:54 +08:00
|
|
|
|
|
|
|
// init props
|
2024-12-06 21:08:24 +08:00
|
|
|
this.rawProps = rawProps || EMPTY_OBJ
|
2024-12-05 16:14:24 +08:00
|
|
|
this.hasFallthrough = hasFallthroughAttrs(comp, rawProps)
|
2024-12-06 21:08:24 +08:00
|
|
|
if (rawProps || comp.props) {
|
|
|
|
const [propsHandlers, attrsHandlers] = getPropsProxyHandlers(comp)
|
|
|
|
this.props = comp.props ? new Proxy(this, propsHandlers!) : {}
|
|
|
|
this.attrs = new Proxy(this, attrsHandlers)
|
|
|
|
} else {
|
|
|
|
this.props = this.attrs = EMPTY_OBJ
|
|
|
|
}
|
|
|
|
|
|
|
|
// init slots
|
2024-12-07 15:12:32 +08:00
|
|
|
this.rawSlots = rawSlots || EMPTY_OBJ
|
2024-12-06 23:10:41 +08:00
|
|
|
this.slots = rawSlots
|
|
|
|
? rawSlots.$
|
|
|
|
? new Proxy(rawSlots, dynamicSlotsProxyHandlers)
|
|
|
|
: rawSlots
|
|
|
|
: EMPTY_OBJ
|
2024-12-04 23:02:15 +08:00
|
|
|
|
2024-12-04 23:50:59 +08:00
|
|
|
if (__DEV__) {
|
2024-12-05 16:14:24 +08:00
|
|
|
// validate props
|
|
|
|
if (rawProps) setupPropsValidation(this)
|
2024-12-04 23:50:59 +08:00
|
|
|
// cache normalized options for dev only emit check
|
|
|
|
this.propsOptions = normalizePropsOptions(comp)
|
|
|
|
this.emitsOptions = normalizeEmitsOptions(comp)
|
|
|
|
}
|
2024-05-29 01:43:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
export function isVaporComponent(
|
|
|
|
value: unknown,
|
|
|
|
): value is VaporComponentInstance {
|
|
|
|
return value instanceof VaporComponentInstance
|
2024-06-16 16:50:36 +08:00
|
|
|
}
|
|
|
|
|
2024-12-08 16:12:08 +08:00
|
|
|
export class SetupContext {
|
2024-12-04 13:50:54 +08:00
|
|
|
attrs: Record<string, any>
|
2024-12-08 16:12:08 +08:00
|
|
|
emit: EmitFn
|
|
|
|
slots: Readonly<StaticSlots>
|
2024-12-04 13:50:54 +08:00
|
|
|
expose: (exposed?: Record<string, any>) => void
|
2024-06-16 16:50:36 +08:00
|
|
|
|
2024-12-04 13:50:54 +08:00
|
|
|
constructor(instance: VaporComponentInstance) {
|
|
|
|
this.attrs = instance.attrs
|
2024-12-08 16:12:08 +08:00
|
|
|
this.emit = instance.emit
|
|
|
|
this.slots = instance.slots
|
2024-12-04 13:50:54 +08:00
|
|
|
this.expose = (exposed = {}) => {
|
|
|
|
instance.exposed = exposed
|
2024-06-16 16:50:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-12-06 11:10:35 +08:00
|
|
|
|
2024-12-06 21:08:24 +08:00
|
|
|
/**
|
|
|
|
* Used when a component cannot be resolved at compile time
|
|
|
|
* and needs rely on runtime resolution - where it might fallback to a plain
|
|
|
|
* element if the resolution fails.
|
|
|
|
*/
|
2024-12-06 11:10:35 +08:00
|
|
|
export function createComponentWithFallback(
|
|
|
|
comp: VaporComponent | string,
|
2024-12-07 15:12:32 +08:00
|
|
|
rawProps: RawProps | null | undefined,
|
|
|
|
rawSlots: RawSlots | null | undefined,
|
2024-12-06 11:10:35 +08:00
|
|
|
isSingleRoot?: boolean,
|
|
|
|
): HTMLElement | VaporComponentInstance {
|
|
|
|
if (!isString(comp)) {
|
2024-12-07 15:12:32 +08:00
|
|
|
return createComponent(comp, rawProps, rawSlots, isSingleRoot)
|
2024-12-06 11:10:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// eslint-disable-next-line no-restricted-globals
|
|
|
|
const el = document.createElement(comp)
|
|
|
|
|
|
|
|
if (rawProps) {
|
|
|
|
renderEffect(() => {
|
|
|
|
let classes: unknown[] | undefined
|
|
|
|
let styles: unknown[] | undefined
|
|
|
|
const resolved = resolveDynamicProps(rawProps)
|
|
|
|
for (const key in resolved) {
|
|
|
|
const value = resolved[key]
|
|
|
|
if (key === 'class') (classes ||= []).push(value)
|
|
|
|
else if (key === 'style') (styles ||= []).push(value)
|
|
|
|
else setDynamicProp(el, key, value)
|
|
|
|
}
|
|
|
|
if (classes) setClass(el, classes)
|
|
|
|
if (styles) setStyle(el, styles)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-12-07 21:43:08 +08:00
|
|
|
if (rawSlots) {
|
|
|
|
if (rawSlots.$) {
|
|
|
|
// TODO dynamic slot fragment
|
|
|
|
} else {
|
|
|
|
insert(getSlot(rawSlots, 'default')!(), el)
|
|
|
|
}
|
2024-12-07 15:12:32 +08:00
|
|
|
}
|
2024-12-06 11:10:35 +08:00
|
|
|
|
|
|
|
return el
|
|
|
|
}
|
2024-12-08 21:22:51 +08:00
|
|
|
|
|
|
|
export function mountComponent(
|
|
|
|
instance: VaporComponentInstance,
|
|
|
|
parent: ParentNode,
|
|
|
|
anchor: Node | null | 0,
|
|
|
|
): void {
|
|
|
|
if (!instance.isMounted) {
|
|
|
|
if (instance.bm) invokeArrayFns(instance.bm)
|
|
|
|
insert(instance.block, parent, anchor)
|
|
|
|
// queuePostFlushCb(() => {
|
|
|
|
if (instance.m) invokeArrayFns(instance.m)
|
|
|
|
instance.isMounted = true
|
|
|
|
// })
|
|
|
|
} else {
|
|
|
|
insert(instance.block, parent, anchor)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function unmountComponent(
|
|
|
|
instance: VaporComponentInstance,
|
|
|
|
parent: ParentNode,
|
|
|
|
): void {
|
|
|
|
if (instance.isMounted && !instance.isUnmounted) {
|
|
|
|
if (instance.bum) invokeArrayFns(instance.bum)
|
|
|
|
// TODO invoke unmount recursively for children
|
|
|
|
remove(instance.block, parent)
|
|
|
|
// queuePostFlushCb(() => {
|
|
|
|
if (instance.um) invokeArrayFns(instance.um)
|
|
|
|
instance.isUnmounted = true
|
|
|
|
// })
|
|
|
|
}
|
|
|
|
}
|