虚拟DOM
话不多说 直接上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>虚拟DOM</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<div>
<p>hello1</p>
<p>hello2</p>
<p>hello3</p>
</div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
<script>
// 怎么将真正的DOM转换为虚拟DOM 与深拷贝类似
// <div> = >{tag: 'div'}
// 文本节点 => {tag: undefined,value:'文本节点'}
// <div class="red" title="title"> ==>{tag:'div',data:{title:'title',class:'red'}}
// <div> <div class='child'> </div> == >{tag:"div",children:{tag:'div',data:{class:'child'}}}
class VNode {
constructor(tag, data, value, type) {
this.tag = tag && tag.toLowerCase();
this.data = data;
this.value = value;
this.children = [];
this.type = type
}
appendChild(vnode) {
this.children.push(vnode)
}
}
// 使用递归遍历生成虚拟DOM Vue源码使用的是栈存储父元素来递归生成
function getVNode(node) {
let nodeType = node.nodeType;
let _vnode = null;
if (nodeType === 1) {
// 元素节点
let nodeTag = node.nodeName;
let attrs = node.attributes; //attrs 是一个伪数组 转换成对象
let _attrObj = {}; // 它存放的是元素的属性 就是上面的data里面放的
for (let i = 0; i < attrs.length; i++) { // attrs[i] 属性节点 nodeType == 2 nodeName是属性的名称 nodeValue是属性的值
_attrObj[attrs[i].nodeName] = attrs[i].nodeValue;
}
_vnode = new VNode(nodeTag, _attrObj, undefined, node.nodeType);
//考虑node的子元素
let childNodes = node.childNodes; // 他是传进来的node节点的下面的子节点
// 遍历所有的子节点 并生成所有子节点的虚拟DOM
for (let i = 0; i < childNodes.length; i++) {
_vnode.appendChild(getVNode(childNodes[i]));//递归
}
} else if (nodeType === 3) {
_vnode = new VNode(undefined, undefined, node.nodeValue, node.nodeType);
}
return _vnode;
}
let root = document.querySelector("#root")
let Vroot = getVNode(root);
console.log(Vroot)
</script>
</body>
</html>
这里面有一些原生js的DOM节点操作 过几天会整理一期发出来。