一、代码如下
<body>
<div id="root">
<div>
<div class="boxf" title="内容">
<p style="font-size: 24px;" id="section">hello</p>
<p>hello</p>
<p>hello</p>
</div>
<ul>
<li>1</li>
<li>2</li>
<li style="color: blue;">3</li>
</ul>
</div>
</div>
<script>
// 真实 DOM 转化成 虚拟 DOM
class Vnode {
/**
* tag 表示元素节点元素名称nodeName,例如 div; 文本节点 nodeName 值为 undefined
* data 表示元素节点上的 属性对象,例如{title: '123', id: 'box'}; 文本节点 没有属性
* value 表示文本节点的 nodeValue; 元素节点的 nodeValue 为 undefined
* type 表示节点的类型,元素节点的 nodeType 值为 1, 文本节点的 nodeType 值为 3
*/
constructor(tag, data, value, type) {
// 文本节点没有 nodeName, 所以 tag 要进行 判断,不然会报错
this.tag = tag && tag.toLowerCase();
this.data = data;
this.value = value;
this.type = type;
this.children = [];
}
// 加上子节点的虚拟 DOM
appendChild(vNode) {
this.children.push(vNode);
}
}
// 把真实 DOM 转化成 虚拟 DOM
function getVnode(node) {
let nodeType = node.nodeType;
let _vnode = null;
if (nodeType === 1) {
// 元素节点
let NodeName = node.nodeName;
let attrs = node.attributes;
let attrsObj = {};
for (var i = 0; i < attrs.length; i++) {
attrsObj[attrs[i].nodeName] = attrs[i].nodeValue;
}
_vnode = new Vnode(NodeName, attrsObj, undefined, nodeType);
let childNodes = node.childNodes;
for (var i = 0; i < childNodes.length; i++) {
_vnode.appendChild(getVnode(childNodes[i]))
}
} else if (nodeType == 3) {
_vnode = new Vnode(undefined, undefined, node.nodeValue, nodeType);
}
return _vnode;
}
let root = document.querySelector('#root');
let rootVnode = getVnode(root);
console.log(rootVnode, '虚拟 Dom')
// 把虚拟 DOM 转化成真实 DOM
function parseVnode(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 => {
let attrName = key;
let attrValue = attrs[key];
_node.setAttribute(attrName, attrValue);
})
// 给元素节点添加子元素节点
let childrenNodes = vnode.children;
for (var i = 0; i < childrenNodes.length; i++) {
_node.appendChild(parseVnode(childrenNodes[i]))
}
}
return _node;
}
let dom = parseVnode(rootVnode);
console.log(dom, '真实 Dom')
</script>
</body>
二、真实 DOM 转 虚拟 DOM 结果如下
三、虚拟 DOM 转 真实 DOM 结果如下
转真实后的 DOM 跟我们上面的 body 中的元素一致。