真实DOM解析流程
浏览器渲染的过程主要包括以下五步:
- 浏览器获取到 HTML 文档并解析 DOM 树
- 解析 CSS 构建层叠样式表模型CSSOM(CSS Object Model)
- 将 DOM Tree 和 CSSOM 合并成一个 Render Tree
- 有了Render Tree,浏览器便能获取到每个节点的 CSS 定义和从属关系,从而可以计算出每个节点的现实位置
-
通过上一步的计算规则进行绘制页面
虚拟DOM产生的背景
用原生 js 或 jquery 去操作 DOM 时,浏览器会从构建 DOM 树到绘制全部执行一遍。
当我们频繁操作 DOM 的时候,浏览器并不知道下一次操作 DOM 是什么时候,所以每次 DOM 有更新的时候,浏览器都会执行一遍上面的流程,比如计算 DOM 坐标值时可能就会大量的浪费性能,在计算完这次的坐标的时候,紧接着 DOM 的位置又发生变化,又要重新计算,前一次计算所消耗的性能就白白浪费了,操作太频繁的话还会造成页面卡顿。虚拟 DOM 的出现就是为了解决这个问题。
虚拟DOM原理
虚拟DOM就是利用js运行速度快的这一优点对操作DOM进行优化的,用js模拟DOM树,在js中处理DOM的操作再渲染,简单概括分为以下三点:
- 用javascript对象模拟DOM树并且渲染DOM树;
- 通过 diff算法 比较新旧DOM树,得到差异的对象;
- 将差异的对象应用到渲染的DOM树中。
真实DOM:
<div id="app">
哈哈
<p>123</p>
</div>
虚拟DOM:
var vNode = {
tag: 'div',
props: {id: 'app'},
children: [
{
tag: 'p',
props: {},
children: [],
context: '123'
}
],
context: '哈哈'
}
虚拟DOM实现:
function createComponent(tag) {
let child = [];
for(let i = 0; i < tag.children.length; i++) {
if(tag.children[i].children.length <= 0) {
child[i] = {
tag: tag.children[i].nodeName.toLowerCase(),
props: tag.children[i].attributes,
context: tag.children[i].innerText,
children: []
};
} else {
child[i] = createComponent(tag.children[i]);
}
}
let vNode = {
tag: tag.nodeName.toLowerCase(),
props: tag.attributes,
children: child,
context: tag.childNodes[0].nodeValue
}
return vNode;
}
下一篇 Diff算法:https://www.jianshu.com/p/cdb4ad82df20