vue3-core/packages/runtime-vapor/src/render.ts

81 lines
2.3 KiB
TypeScript
Raw Normal View History

2023-12-06 14:59:11 +08:00
import { reactive } from '@vue/reactivity'
2023-11-17 03:01:19 +08:00
import {
2023-12-06 14:59:11 +08:00
type ComponentInternalInstance,
type FunctionalComponent,
type ObjectComponent,
2023-12-03 18:36:01 +08:00
createComponentInstance,
setCurrentInstance,
2023-12-04 16:08:15 +08:00
unsetCurrentInstance,
2023-12-03 18:36:01 +08:00
} from './component'
2023-12-04 16:08:15 +08:00
import { invokeDirectiveHook } from './directives'
2023-12-06 14:59:11 +08:00
import { insert, remove } from './dom'
2023-11-17 03:01:19 +08:00
export type Block = Node | Fragment | Block[]
export type ParentBlock = ParentNode | Node[]
2023-11-26 02:13:59 +08:00
export type Fragment = { nodes: Block; anchor: Node }
2023-12-06 14:59:11 +08:00
export type BlockFn = (props: any, ctx: any) => Block
2023-11-17 03:01:19 +08:00
export function render(
2023-12-06 14:59:11 +08:00
comp: ObjectComponent | FunctionalComponent,
2023-12-01 01:28:16 +08:00
container: string | ParentNode,
): ComponentInternalInstance {
const instance = createComponentInstance(comp)
2023-12-03 18:36:01 +08:00
setCurrentInstance(instance)
mountComponent(instance, (container = normalizeContainer(container)))
return instance
2023-11-17 03:01:19 +08:00
}
export function normalizeContainer(container: string | ParentNode): ParentNode {
return typeof container === 'string'
? (document.querySelector(container) as ParentNode)
: container
}
2023-12-06 14:59:11 +08:00
export function mountComponent(
instance: ComponentInternalInstance,
2023-12-01 01:28:16 +08:00
container: ParentNode,
2023-12-06 14:59:11 +08:00
) {
instance.container = container
2023-12-04 16:08:15 +08:00
setCurrentInstance(instance)
2023-12-06 14:59:11 +08:00
const block = instance.scope.run(() => {
const { component } = instance
const props = {}
const ctx = { expose: () => {} }
const setupFn =
typeof component === 'function' ? component : component.setup
const state = setupFn(props, ctx)
if (state && '__isScriptSetup' in state) {
return (instance.block = component.render(reactive(state)))
} else {
return (instance.block = state as Block)
}
})!
2023-12-04 16:08:15 +08:00
invokeDirectiveHook(instance, 'beforeMount')
insert(block, instance.container)
instance.isMounted = true
2023-12-04 16:08:15 +08:00
invokeDirectiveHook(instance, 'mounted')
// TODO: lifecycle hooks (mounted, ...)
// const { m } = instance
// m && invoke(m)
}
2023-12-06 14:59:11 +08:00
export function unmountComponent(instance: ComponentInternalInstance) {
const { container, block, scope } = instance
2023-12-04 16:08:15 +08:00
invokeDirectiveHook(instance, 'beforeUnmount')
scope.stop()
block && remove(block, container)
instance.isMounted = false
2023-12-04 16:08:15 +08:00
invokeDirectiveHook(instance, 'unmounted')
unsetCurrentInstance()
// TODO: lifecycle hooks (unmounted, ...)
// const { um } = instance
// um && invoke(um)
}