# createElm
function createElm(
vnode,
insertedVnodeQueue,
parentElm,
refElm, // nextSibiling
nested,
ownerArray,
index
) {
if (isDef(vnode.elm) && isDef(ownerArray)) {
vnode = ownerArray[index] = cloneVNode(vnode)
}
vnode.isRootInsert = !nested
/*
* createComponent 和 render 中的不是同一个函数
* 如果 vnode 是一个组件, 则执行 init 钩子,创建组件实例并挂载
* 然后为组件执行各个模块的 create 钩子
* 如果组件被 keep-alive 包裹, 则激活组件
* 组件走动这就 return 了
*/
if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) return
// 不是组件 Root
const data = vnode.data
const children = vnode.children
const tag = vnode.tag
if (isDef(tag)) {
if (process.env.NODE_ENV !== 'production') {
if (data && data.pre) {
creatingElmInPre++
}
// 未知标签
if (isUnKnownElement(vnode, creatingElmInPre)) {
warn('...')
}
}
// 创建新节点
vnode.elm = vnode.ns
? nodeOps.createElementNS(vnode.ns, tag)
: nodeOps.createElement(tag, vnode)
// 如果 style 里设置了 scope 则为标签添加 hash
setScope(vnode)
// 递归创建所有子节点
createChildren(vnode, children, insertedVnodeQueue)
if (isDef(data)) {
invokeCreateHooks(vnode, insertedVnodeQueue)
}
// 将节点插入父节点, 如果有 refElm 则将 DOM 插入到 refElm 之前
insert(parentElm, vnode.elm, refElm)
if (process.env.NODE_ENV !== 'production' && data && data.pre) {
creatingElmIInVPre--
}
} else if (isTrue(vnode.isComment)) {
// 注释节点
vnode.elm = nodeOps.createComment(vnode.text)
insert(parentElm, vnode.elm, refElm)
} else {
// 文本节点
vnode.elm = nodeOps.createTextNode(vnode.text)
insert(parentElm, vnode.elm, refElm)
}
}
# createComponent
function createComponent(vnode, insertedVnodeQueue, parentElm, refElm) {
// 获取 vnode.data 对象
let i = vnode.data
if (isDef(i)) {
// 未创建实例的组件都会先返回false,创建对应的 element 并 insert
// 组件实例被 keepAlive 包裹,不会销毁 componentInstance 则会直接 insert 不会重新 createElm
const isReactivated = isDef(vnode.componentInstance) && i.keepAlive
// 执行 vnode.data.init 函数
// _c 会注册 init hooks 会将 VNode.componentInstance 设置为对应的 Vue 实例
if (isDef(i = i.hook) && isDef(i = i.init)) {
i(vnode, false/* hydrating */)
}
if (isDef(vnode.componentInstance)) {
initComponent(vnode, insertdVnodeQueue)
insert(parentElm, vnode.elm, refElm)
// 如果存在 componentInstance 并且 keepAlive (缓存) 则不
if (isTrue(isReactivated)) {
// 组件被 keep-alive 包裹的情况,激活组件
reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm)
}
return true
}
}
}
# createChildren
function createChildren(vnode, children, insertedVnodeQueue) {
if (Array.isArray(children)) {
for (let i = 0; i < children.length; i++) {
createElm(children[i], insertedQueue, vnode.elm, null, true, children, i)
}
} else if (isPrimitive(vnode.text)) {
nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(String(vnode.text)))
}
}