createElm | |
function createElm(vnode: VNode, insertedVnodeQueue: VNodeQueue): Node {
let i: any;
let data = vnode.data;
if (data !== undefined) {
// 执行用户设置的init钩子函数
const init = data.hook?.init; // 用户传递的init函数
if (isDef(init)) {
init(vnode); // 调用init后,可能改变vnode的内容
data = vnode.data; // 所以再次进行赋值;
}
}
// 把vnode转换成真实DOM对象(没有渲染到页面)
const children = vnode.children;
const sel = vnode.sel;
if (sel === "!") {
// 注释节点
if (isUndef(vnode.text)) {
vnode.text = "";
}
vnode.elm = api.createComment(vnode.text!);
} else if (sel !== undefined) {
// 如果选择器不为空
// 解析选择器
// Parse selector
const hashIdx = sel.indexOf("#"); // #位置
const dotIdx = sel.indexOf(".", hashIdx); // .的位置
const hash = hashIdx > 0 ? hashIdx : sel.length;
const dot = dotIdx > 0 ? dotIdx : sel.length;
const tag =
hashIdx !== -1 || dotIdx !== -1
? sel.slice(0, Math.min(hash, dot))
: sel; // 标签名
const elm = (vnode.elm =
isDef(data) && isDef((i = data.ns))
? api.createElementNS(i, tag, data)
: api.createElement(tag, data));
if (hash < dot) elm.setAttribute("id", sel.slice(hash + 1, dot));
if (dotIdx > 0)
elm.setAttribute("class", sel.slice(dot + 1).replace(/\./g, " "));
// 执行模块的create钩子函数
for (i = 0; i < cbs.create.length; ++i) cbs.create[i](emptyNode, vnode);
// 如果vnode中有子节点,创建子vnode对应的DOM元素并追加到DOM树上;
if (is.array(children)) {
for (i = 0; i < children.length; ++i) {
const ch = children[i];
if (ch != null) {
// 如果子节点不为空,递归调用子节点,追加在对应父节点上
api.appendChild(elm, createElm(ch as VNode, insertedVnodeQueue));
}
}
} else if (is.primitive(vnode.text)) {
// 如果vnode的text值是 string/number,创建文本节点并追加到 DOM树上
api.appendChild(elm, api.createTextNode(vnode.text));
}
const hook = vnode.data!.hook;
if (isDef(hook)) {
// 执行用户传入的钩子 create
hook.create?.(emptyNode, vnode);
if (hook.insert) {
// 把vnode 添加到队列中,为后续执行insert钩子做准备
insertedVnodeQueue.push(vnode);
}
}
} else {
// 选择器为空,创建文本节点
vnode.elm = api.createTextNode(vnode.text!);
}
// 返回新创建的DOM
return vnode.elm;
}