VirtualDom: patch関数を実装する前に
https://ubugeeei.github.io/chibivue/10-minimum-example/040-minimum-virtual-dom.html#patch-関数の実装を行う前に
patch関数の実装をしやすくするために、一旦ここでリファクタを行っておく
1. vnode.ts に createVNode と言う関数を作っておいて、h 関数からはそれを呼ぶようにする
code: packages/runtime-core/vnode.ts
export function createVNode(
type: string,
props: VNodeProps | null,
children: (VNode | string)[],
): VNode {
const vnode: VNode = { type, props, children }
return vnode
}
code: packages/runtime-core/h.ts
export function h(
type: string,
props: VNodeProps,
children: (VNode | string)[],
) {
return createVNode(type, props, children)
}
2. テキストを文字列として扱うのはやめて、VNodeに統一する
テキスト も実際にはただの文字列ではなく、HTML の TextElement として存在するので、文字列以上の情報を含む
それらの周辺情報を扱うためにも VNode として扱いたい
code: ts
// 例: "hello"というテキストだった場合
{
type: Text,
props: null,
children: "hello"
}
code: packages/runtime-core/vnode.ts
// テキストを Symbol を用いて、VNode のtypeとして持たせる
export const Text = Symbol();
// htmlTag の string もしくは テキスト(Symbol)
export type VNodeTypes = string | typeof Text;
export interface VNode<HostNode = any> {
type: VNodeTypes;
props: VNodeProps | null;
children: VNodeNormalizedChildren;
}
export interface VNodeProps {
key: string: any;
}
// normalize後の型
// NOTE: normalizeした後なのに string があるのはなぜ?
export type VNodeNormalizedChildren = string | VNodeArrayChildren;
export type VNodeArrayChildren = Array<VNodeArrayChildren | VNodeChildAtom>;
export type VNodeChild = VNodeChildAtom | VNodeArrayChildren;
type VNodeChildAtom = VNode | string;
export function createVNode(
type: VNodeTypes,
props: VNodeProps | null,
children: VNodeNormalizedChildren,
){..} // 省略
// normalize 関数を実装。(renderer.tsで使う)
export function normalizeVNode(child: VNodeChild): VNode {
if (typeof child === "object") {
return { ...child } as VNode;
} else {
// string だった場合に VNode に変換する
return createVNode(Text, null, String(child));
}
}