Vue解析总纲
上一节:防Vue系列-03:添加解析data.xxx.xxx函数
virtual DOM(虚拟dom,VNode)
-
为什么要用VNode,主要是考虑性能问题,频繁的操作dom会有点性能问题,主要是我们只修改一部分的数据,却要重新渲染整个dom。
-
接下来让我们来初步了解一下VNode
-
思考怎么将一下的dom 标签转换成,VNode对象形式
<div id="root" class="theme">
<h2 class="a" title="hello">hello1</h2>
<div>hello2</div>
<div>hello3</div>
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
</div>
</div>
- 首先先创建一个VNode类
/*
*@params tag:String 'div||span||h1'
*@params data:Object '{id:'root,class:'theme'...}'
*@params value:String 'nodeValue || undefined'
*@params type:Number 'nodeType=1 || 2 ||3 '
*/
class VNode {
constructor(tag, data, value, type) {
this.tag = tag && tag.toLocaleLowerCase();
this.data = data;
this.value = value;
this.type = type;
this.children = []; //子节点数组,默认[]
}
// 添加子节点
appendChild(childrenNode) {
this.children.push(childrenNode);
}
}
- 创建一个生成VNode函数getVNode
/*
*@params realDom:HtmlElement '真实的DOM对象'
*@return vNode:Object '虚拟的DOM对象'
*/
function getVNode(realDom) {
let nodeType = realDom.nodeType; //节点类型
let _vode = null;
// 元素节点
if (nodeType === 1) {
let tag = realDom.nodeName; //标签名
let attributes = realDom.attributes; //对象属性
let childNodes = realDom.childNodes; //子节点
// 获取属性对象
let data = {};
for (let i = 0; i < attributes.length; i++) {
let key = attributes[i].nodeName;
let value = attributes[i].value;
data[key] = value;
}
// 生成虚拟dom对象
_vode = new VNode(tag, data, undefined, nodeType);
//如果有子节点,添加子节点,递归遍历 ===本节难点!!!===
for (let i = 0; i < childNodes.length; i++) {
_vode.appendChild(getVNode(childNodes[i]));
}
}
// 文本节点
else if (nodeType === 3) {
_vode = new VNode(undefined, undefined, realDom.nodeValue, nodeType);
}
return _vode; //虚拟dom
}
- 这样就拿到了指定DOM的Vnode了