- 根据node节点来生成一个VNode(vue中是是用字符串模版进行ast抽象树在进行VNode生成)
/** 虚拟 DOM 构造函数 */
class VNode {
constructor(tag, data, value, type) {
this.tag = tag && tag.toLowerCase();
this.data = data;
this.value = value;
this.type = type;
this.children = [];
}
appendChild(vnode) {
this.children.push(vnode);
}
}
/**根据node生成一个虚拟DOM树 */
function getVNode(node) {
let _vnode = null;
let nodeType = node.nodeType;
if (nodeType === 3) {
_vnode = new VNode(undefined, undefined, node.nodeValue, nodeType);
} else if (nodeType === 1) {
// 元素
let nodeName = node.nodeName;
let attrs = node.attributes; // attrs[ i ] 属性节点 ( nodeType == 2 )
let attr_obj = {};
for (let i = 0; i < attrs.length; i++) {
attr_obj[attrs[i].nodeName] = attrs[i].nodeValue;
}
_vnode = new VNode(nodeName, attr_obj, undefined, nodeType);
// 考虑 node 的子元素
let childNodes = node.childNodes;
for (let i = 0; i < childNodes.length; i++) {
_vnode.appendChild(getVNode(childNodes[i])); // 递归
}
}
return _vnode;
}
/**将vnode转成node */
function parseNode(vnode) {
let type = vnode.type;
let _node = null;
if (type === 3) {
return document.createTextNode(vnode.value);
} else if (type === 1) {
_node = document.createElement(vnode.tag);
let attrs = vnode.data;
Object.keys(attrs).forEach(key => {
_node.setAttribute(key, attrs[key]);
});
let childrenVNode = vnode.children
if (childrenVNode) {
childrenVNode.forEach(sub => {
_node.appendChild(parseNode(sub));
});
}
return _node;
}
}