虚拟dom生成真实dom
function patch(vNode) {
let tag = vNode.tag; //目标元素 不可或缺
let attrs = vNode.attrs || {}; //属性
let children = vNode.children || [] //子节点
if (!tag) {
return null;
}
//创建对应的dom
let ele = document.createElement(tag);
let attrName;
// 给dom添加属性
for (attrName in attrs) {
if (attrs.hasOwnProperty(attrName)) {
ele.setAttribute(attrName, attrs[attrName])
}
}
// 将子元素添加到目标元素
children.forEach((item) => {
ele.append(create(item)); // 如果子元素还有子元素,递归
});
return ele;
}
更新时候的对比
function updateChildren(vNode, newVnode) {
let children = vNode.children || []; //现有节点
let newChildren = newVnode.children || []; //新节点
//循环每一项
children.forEach((childVnode, index) => {
const newChildrenVnode = newChildren[index];
//第一层没变化
if(childVnode.tag === newChildrenVnode.tag){
updateChildren(childVnode,newChildrenVnode)
}else{
//两者tag不一样
replaceNode(childVnode,newChildrenVnode)
}
})
}
Virtual Dom 的优势在哪里?
举个例子:
你用传统的原生api或jQuery去操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程
当你在一次操作时,需要更新10个DOM节点,浏览器没这么智能,收到第一个更新DOM请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程
而通过VNode,同样更新10个DOM节点,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性attach到DOM树上,避免大量的无谓计算
优势:
- 虚拟 DOM 不会立马进行排版与重绘操作
- 虚拟 DOM 进行频繁修改,然后一次性比较并修改真实 DOM 中需要改的部分,最后在真实 DOM 中进行排版与重绘,减少过多DOM节点排版与重绘损耗
- 虚拟 DOM 有效降低大面积真实 DOM 的重绘与排版,因为最终与真实 DOM 比较差异,可以只渲染局部
- 虚拟 DOM 最大的优势在于抽象了原本的渲染过程,实现了跨平台的能力,而不仅仅局限于浏览器的 DOM,可以是安卓和 IOS 的原生组件和小程序