diff --git a/packages/runtime-vapor/src/component.ts b/packages/runtime-vapor/src/component.ts new file mode 100644 index 000000000..02fc0d3ba --- /dev/null +++ b/packages/runtime-vapor/src/component.ts @@ -0,0 +1,35 @@ +import { EffectScope } from '@vue/reactivity' + +import { Block, BlockFn } from './render' + +export interface ComponentInternalInstance { + uid: number + container: ParentNode + block: Block | null + scope: EffectScope + + component: BlockFn + isMounted: boolean + + // TODO: registory of provides, appContext, lifecycles, ... +} + +let uid = 0 +export const createComponentInstance = ( + component: BlockFn +): ComponentInternalInstance => { + const instance: ComponentInternalInstance = { + uid: uid++, + block: null, + container: null!, // set on mount + scope: new EffectScope(true /* detached */)!, + + component, + isMounted: false + // TODO: registory of provides, appContext, lifecycles, ... + } + return instance +} + +// FIXME: duplicated with runtime-core +export type Data = Record diff --git a/packages/runtime-vapor/src/render.ts b/packages/runtime-vapor/src/render.ts index a5a8c4e07..b5c5a72cd 100644 --- a/packages/runtime-vapor/src/render.ts +++ b/packages/runtime-vapor/src/render.ts @@ -1,10 +1,11 @@ import { + isArray, normalizeClass, normalizeStyle, - toDisplayString, - isArray + toDisplayString } from '@vue/shared' -import { effectScope } from '@vue/reactivity' + +import { ComponentInternalInstance, createComponentInstance } from './component' export type Block = Node | Fragment | Block[] export type ParentBlock = ParentNode | Node[] @@ -14,14 +15,10 @@ export type BlockFn = (props?: any) => Block export function render( comp: BlockFn, container: string | ParentNode -): () => void { - const scope = effectScope() - const block = scope.run(() => comp())! - insert(block, (container = normalizeContainer(container))) - return () => { - scope.stop() - remove(block, container as ParentNode) - } +): ComponentInternalInstance { + const instance = createComponentInstance(comp) + mountComponent(instance, (container = normalizeContainer(container))) + return instance } export function normalizeContainer(container: string | ParentNode): ParentNode { @@ -30,6 +27,31 @@ export function normalizeContainer(container: string | ParentNode): ParentNode { : container } +export const mountComponent = ( + instance: ComponentInternalInstance, + container: ParentNode +) => { + instance.container = container + const block = instance.scope.run( + () => (instance.block = instance.component()) + )! + insert(block, instance.container) + instance.isMounted = true + // TODO: lifecycle hooks (mounted, ...) + // const { m } = instance + // m && invoke(m) +} + +export const unmountComponent = (instance: ComponentInternalInstance) => { + const { container, block, scope } = instance + scope.stop() + block && remove(block, container) + instance.isMounted = false + // TODO: lifecycle hooks (unmounted, ...) + // const { um } = instance + // um && invoke(um) +} + export function insert( block: Block, parent: ParentNode,