Appearance
创建根节点的代码生成节点
createRootCodegen
- createRootCodegen 目的就是 为 root 这个虚拟的 ast 根节点创建一个代码生成节点
- 如果 root 的子节点 children 是单个元素节点 就将 root 转换成一个 block 节点 把这个 child 的 codegenNode 赋值给 root 的 codegenNode
- 如果 root 的子节点 children 是多个节点 返回一个 fragement 的代码生成节点 并赋值给 root 的 codegenNode
- createRootCodegen 完成之后 把转换 ast 节点的过程中创建的一些上下文数据赋值给 root 节点对应的属性
ts
function createRootCodegen(root: RootNode, context: TransformContext) {
const { helper } = context
const { children } = root
if (children.length === 1) {
const child = children[0]
// if the single child is an element, turn it into a block.
if (isSingleElementRoot(root, child) && child.codegenNode) {
// single element root is never hoisted so codegenNode will never be
// SimpleExpressionNode
const codegenNode = child.codegenNode
if (codegenNode.type === NodeTypes.VNODE_CALL) {
makeBlock(codegenNode, context)
}
root.codegenNode = codegenNode
} else {
// - single <slot/>, IfNode, ForNode: already blocks.
// - single text node: always patched.
// root codegen falls through via genNode()
root.codegenNode = child
}
} else if (children.length > 1) {
// root has multiple nodes - return a fragment block.
let patchFlag = PatchFlags.STABLE_FRAGMENT
let patchFlagText = PatchFlagNames[PatchFlags.STABLE_FRAGMENT]
// check if the fragment actually contains a single valid child with
// the rest being comments
if (
__DEV__ &&
children.filter(c => c.type !== NodeTypes.COMMENT).length === 1
) {
patchFlag |= PatchFlags.DEV_ROOT_FRAGMENT
patchFlagText += `, ${PatchFlagNames[PatchFlags.DEV_ROOT_FRAGMENT]}`
}
root.codegenNode = createVNodeCall(
context,
helper(FRAGMENT),
undefined,
root.children,
patchFlag + (__DEV__ ? ` /* ${patchFlagText} */` : ``),
undefined,
undefined,
true,
undefined,
false /* isComponent */
)
} else {
// no children = noop. codegen will return null.
}
}