真實DOM解析流程
瀏覽器渲染的過程主要包括以下五步:
瀏覽器獲取到 HTML 文檔并解析 DOM 樹
- 解析 CSS 構(gòu)建層疊樣式表模型CSSOM(CSS Object Model)
- 將 DOM Tree 和 CSSOM 合并成一個 Render Tree
- 有了Render Tree,瀏覽器便能獲取到每個節(jié)點的 CSS 定義和從屬關(guān)系,從而可以計算出每個節(jié)點的現(xiàn)實位置
- 通過上一步的計算規(guī)則進行繪制頁面

image.png
虛擬DOM產(chǎn)生的背景
用原生 js 或 jquery 去操作 DOM 時,瀏覽器會從構(gòu)建 DOM 樹到繪制全部執(zhí)行一遍。
當(dāng)我們頻繁操作 DOM 的時候,瀏覽器并不知道下一次操作 DOM 是什么時候,所以每次 DOM 有更新的時候,瀏覽器都會執(zhí)行一遍上面的流程,比如計算 DOM 坐標(biāo)值時可能就會大量的浪費性能,在計算完這次的坐標(biāo)的時候,緊接著 DOM 的位置又發(fā)生變化,又要重新計算,前一次計算所消耗的性能就白白浪費了,操作太頻繁的話還會造成頁面卡頓。虛擬 DOM 的出現(xiàn)就是為了解決這個問題。
虛擬DOM原理
虛擬DOM就是利用js運行速度快的這一優(yōu)點對操作DOM進行優(yōu)化的,用js模擬DOM樹,在js中處理DOM的操作再渲染,簡單概括分為以下三點:
- 用javascript對象模擬DOM樹并且渲染DOM樹;
- 通過 diff算法 比較新舊DOM樹,得到差異的對象;
- 將差異的對象應(yīng)用到渲染的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實現(xiàn):
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;
}