天天看點

【React】虛拟 DOM 和 Diff 算法

文章目錄

    • 一、虛拟DOM
    • 二、Diff算法

一、虛拟DOM

  • DOM樹的概念:一個網頁呈現的過程
1. 浏覽器請求伺服器擷取頁面HTML代碼
2. 浏覽器要現在記憶體中,解析DOM結構,并在浏覽器記憶體中,渲染出一顆DOM樹;
3. 浏覽器把DOM樹,呈現到頁面上;
           
  • 思考:
1. 如何才能把性能做到最優?
按需渣染頁面;(隻重新渲染更新的資料所對應的頁面元素)
2. 如何實作頁面的按需更新呢?
擷取記憶體中的新舊兩棵DOM,進行對比,得到需要被按需更新的DOM元素;
3. 如何擷取到新舊DOM樹,進而實作 DOM樹的對比呢?
程式員手動模拟新舊兩棵DOM樹
分析:浏覽器中,并沒有直接提供 擷取DOM樹的API;是以,我們無法拿到浏覽器記憶體中的DOM樹;
4. 程式員如何手動模拟DOM樹?
就是 React中虛拟DOM的概念;
5. 什麼是虛拟DOM?
用JS對象的形式,來模拟頁面上DOM嵌套關系;(虛拟DOM是以JS對象的形式存在的; )
6. 總結:
本質:用JS對象來模拟DOM元素和嵌套關系;
目的:就是為了實作頁面元素的高效更新;
           
  • 優點:
1. 減少DOM操作:

以前更新資料的方式:
有1萬個節點資料是循環渲染上去的,就要重新渲染1萬次,但是其實它可能隻有10個資料發生了改變,十分消耗性能

按需加載來更新資料:
虛拟dom可以把多次操作合并為一次操作,比如:以前添加100個節點,隻能一個接一個的操作
虛拟dom借助diff算法可以把多餘的操作省略,比如:以前100個節點,但其實隻有2個新增

2. 跨平台:
虛拟DOM不僅可以變成DOM
還可以變成小程式、iOS應用、安卓應用
因為虛拟DOM本質上隻是一個JS對象

           
  • 虛拟DOM長什麼樣子?
// react中的虛拟dom
const rNode = {
	key:null;
	props:{
		children:[	// 子元素們
			{type:"span", ...},
			{type:"span", ...},
		],
		className:"red",// 标簽上的屬性
		onClick:()=>{},// 事件
	},
	ref:null,
	type:"div",// 标簽名或元件名
	...
}
           
// vue中的虛拟dom
const vNode = {
	type:"div",// 标簽名或元件名
	data:{		
		class:"red",// 标簽上的屬性
		on:{
			click: ()=>{},// 事件
		}
	},
	children:[	// 子元素們
		{type:"span", ...},
		{type:"span", ...},
	],
	...
}
           

二、Diff算法

【React】虛拟 DOM 和 Diff 算法

Diff算法:虛拟DOM的核心

- 隻比較同一層級,不跨級比較
- 标簽名不同,直接删除,不繼續深度比較
- 标簽名相同,key相同,就認為是相同節點,不繼續深度比較
1. Tree diff:
将新舊兩棵樹逐層對比,找出哪些節點需要更親
如果節點是元件就看:Component diff
如果節點是标簽就看:Element diff
2. Component diff:
如果節點是元件,就先看元件類型
類型不同直接替換(删除舊的)
類型相同則隻更新屬性
3. Element diff:
如果節點是原生标簽,則看标簽名
标簽名不同直接替換,相同則隻更新屬性
然後進入标簽後代做 Tree diff(遞歸)
           
  • Diff算法缺點:

繼續閱讀