挂载Element
const mountElement = (
vnode,
container,
anchor,
parentComponent,
parentSuspense,
isSVG,
optimized
) => {
let el
let vnodeHook
const {
type,
props,
shapeFlag,
transition,
scopeId,
patchFlag,
dirs,
} = vnode
{
// 创建dom节点
el = vnode.el = hostCreateElement(vnode.type, isSVG, props && props.is)
if (shapeFlag & 8 /* TEXT_CHILDREN */) {
hostSetElementText(el, vnode.children)
} else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {
// 处理数组子节点
mountChildren(
vnode.children,
el,
null,
parentComponent,
parentSuspense,
isSVG && type !== 'foreignObject',
optimized || !!vnode.dynamicChildren
)
}
// vnode的props:例如 { id: 'search', type:'button' }
if (props) {
for (const key in props) {
if (!isReservedProp(key)) {
hostPatchProp(
el,
key,
null,
props[key],
isSVG,
vnode.children,
parentComponent,
parentSuspense,
unmountChildren
)
}
}
}
// 设置dom的一些attr属性
setScopeId(el, scopeId, vnode, parentComponent)
}
// 将虚拟节点缓存给dom,且不能被枚举出来。
{
Object.defineProperty(el, '__vnode', {
value: vnode,
enumerable: false,
})
Object.defineProperty(el, '__vueParentComponent', {
value: parentComponent,
enumerable: false,
})
}
// 把创建的 element,插入到节点中
hostInsert(el, container, anchor)
}
总结
- 创建一个element,赋值给 vnode.el
- 判断子节点类型
- 子节点是文本:创建文本
- 子节点是数组:执行方法
mountChildren
,批量挂载子节点
- 设置element的
props
- 设置element的
attr
属性 - 把创建的element插入到
container
中