--- /dev/null
+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<string, unknown>
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[]
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 {
: 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,