既存実装を整理ベースで考える
https://ubugeeei.github.io/chibivue/10-minimum-example/050-minimum-component.html#既存実装の整理ベースで考える
現状の問題点
実装内容全てを createApp に書く必要がある
解決案
コンポーネントを扱えるようにする
実装
まずは render関数の見直し
render関数内にルートコンポーネントに関する記述がある
実際には、各コンポーネントごとにn1,n2,updateComponent,effectが存在する
ユーザー側でコンポーネントを定義して、それをインスタンス化するようにする
そのインスタンスにn1,n2などの情報を持たせる(閉じ込める)
code: ~/packages/runtime-core/renderer.ts
const render: RootRenderFunction = (rootComponent, container) => {
const componentRender = rootComponent.setup!()
let n1: VNode | null = null
let n2: VNode = null!
const updateComponent = () => {
// 省略
}
const effect = new ReactiveEffect(updateComponent)
effect.run()
}
インスタンスの型を決める
code: ~/packages/runtime-core/component.ts
export interface ComponentInternalInstance {
type: Component // 元となるユーザー定義のコンポーネント (旧 rootComponent (実際にはルートコンポーネントだけじゃないけど))
vnode: VNode // 後述
subTree: VNode // 旧 n1
next: VNode | null // 旧 n2
effect: ReactiveEffect // 旧 effect
render: InternalRenderFunction // 旧 componentRender
update: () => void // 旧 updateComponent
isMounted: boolean
}
export type InternalRenderFunction = {
(): VNodeChild
}
h関数の第一引数にコンポーネントを指定できるようにする
code:~/packages/runtime-core/vnode.ts
export type VNodeTypes = string | typeof Text | object
VNode に component のインスタンスを持たせるようにしておく
code: ~packages/runtime-core/vnode.ts
export interface VNode<HostNode = any> {
// 省略
component: ComponentInternalInstance | null
}
renderer でコンポーネントを扱うようにする
Element や Text 同様 mount と patch を実装する
ガワの実装はpatch関数にobjectの場合の分岐を追加するだけ
mountComponentの実装
コンポーネントのインスタンスを生成
setupの実行とその結果をインスタンスに保持 
ReactiveEffect の生成とそれをインスタンスに保持
updateComponentの実装
render関数に定義して不要な実装を削除
これで Component をレンダリングすることができるようになった!
次回: mountComponentの実装理解から