虚拟dom以及其优点
什么是虚拟dom
虚拟DOM可以认为就是,用JS去按照DOM结构来实现的树形结构对象,你也可以叫做DOM对象;
虚拟dom优点
- 虚拟Dom可以用于SSR以及跨端使用;
- 可以降低使用JavaScript去操作跨线程的庞大Dom所需要的昂贵性能,让Dom操作的性能更高;
- 在去任何手动优化的情况下为你提供不错的性能;
注意: 虚拟dom并不会比真实的都没快,dom-diff不是免费的,但是虚拟dom是在你没有任何手动优化的情况下都给你提供不错的性能,更多关于虚拟dom是不是比真实dom快的文章可以看:尤大知乎回答
虚拟dom实现
创建虚拟dom
创建虚拟dom就是用js对象表示dom对象,具体代码如下:
// 创建虚拟DOM元素的类,构建实例对象,就是用来描述DOM
class Element {
constructor(type, props, children) {
this.type = type;
this.props = props;
this.children = children;
}
}
// 创建虚拟DOM,返回虚拟节点(object)
function createElement(type, props, children) {
return new Element(type, props, children);
}
vue和react也是用这种方法来创建虚拟dom的,该方法接受三个参数分别是type,props和children,
- type:元素类型,例如 "li"、"div"等;
- props:元素身上的属性,如class, style, 自定义属性等;
- children:以数组的形式传入,表示元素子节点;
渲染虚拟dom
渲染阶段是将虚拟都没转化成真是dom的过程,在该过程中对虚拟dom进行递归遍历,并对元素设置相关属性;
// render方法可以将虚拟DOM转化成真实DOM
function render(domObj) {
// 根据type类型来创建对应的元素
let el = document.createElement(domObj.type);
// 再去遍历props属性对象,然后给创建的元素el设置属性
for (let key in domObj.props) {
// 设置属性的方法
setAttr(el, key, domObj.props[key]);
}
// 遍历子节点
// 如果是虚拟DOM,就继续递归渲染
// 不是就代表是文本节点,直接创建
domObj.children.forEach(child => {
child = (child instanceof Element) ? render(child) : document.createTextNode(child);
// 添加到对应元素内
el.appendChild(child);
});
return el;
}
// 设置属性
function setAttr(node, key, value) {
switch(key) {
case 'value':
// node是一个input或者textarea就直接设置其value即可
if (node.tagName.toLowerCase() === 'input' ||
node.tagName.toLowerCase() === 'textarea') {
node.value = value;
} else {
node.setAttribute(key, value);
}
break;
case 'style':
// 直接赋值行内样式
node.style.cssText = value;
break;
default:
node.setAttribute(key, value);
break;
}
}
// 将元素插入到页面内
function renderDom(el, target) {
target.appendChild(el);
}
小结
这以上是虚拟dom的实现,github地址为:github地址,