# React中幾個核心的概念
## 虛擬DOM(Virtual Document Object Model)
### DOM的本質是什么:(了解)
>瀏覽器渲染引擎工作流程都差不多,大致分為5步,**創建DOM樹——創建StyleRules——創建Render樹——布局Layout——繪制Painting**??
?第一步,用HTML分析器,分析HTML元素,**構建一顆DOM樹**(標記化和樹構建)。
? ? 第二步,用CSS分析器,分析CSS文件和元素上的inline樣式,生成頁面的樣式表。
? ? 第三步,將DOM樹和樣式表,關聯起來,構建一顆Render樹(這一過程又稱為Attachment)。每個DOM節點都有**attach方法,接受樣式信息**,返回一個render對象(又名renderer)。這些render對象最終會被構建成一顆Render樹。
? ? 第四步,有了Render樹,瀏覽器開始布局,為每個Render樹上的節點確定一個在顯示屏上出現的精確坐標。
? ? 第五步,Render樹和節點顯示坐標都有了,就調用每個節點**paint方法,把它們繪制**出來。?
? ? **DOM樹的構建是文檔加載完成開始的?**構建DOM數是一個漸進過程,為達到更好用戶體驗,渲染引擎會盡快將內容顯示在屏幕上。**它不必**等到整個HTML文檔解析完畢之后才開始構建render數和布局。
? ? **Render樹是DOM樹和CSSOM樹構建完畢才開始構建的嗎?**這三個過程在實際進行的時候又不是完全獨立,而是會有交叉。會造成一邊加載,一遍解析,一遍渲染的工作現象。
? ? **CSS的解析是從右往左逆向解析的**(從DOM樹的下-上解析比上-下解析效率高),**嵌套標簽越多,解析越慢。**

### JS操作真實DOM的代價
????????用我們傳統的開發模式,原生JS或JQ操作DOM時,瀏覽器會從構建DOM樹開始從頭到尾執行一遍流程。在一次操作中,我需要更新10個DOM節點,瀏覽器收到第一個DOM請求后并不知道還有9次更新操作,因此會馬上執行流程,最終執行10次。
例如,第一次計算完,緊接著下一個DOM更新請求,這個節點的坐標值就變了,前一次計算為無用功。計算DOM節點坐標值等都是白白浪費的性能。即使計算機硬件一直在迭代更新,操作DOM的代價仍舊是昂貴的,頻繁操作還是會出現頁面卡頓,影響用戶體驗。
### 為什么需要虛擬DOM,它有什么好處?
? Web界面由DOM樹(樹的意思是數據結構)來構建,當其中一部分發生變化時,其實就是對應某個DOM節點發生了變化,
????????虛擬DOM就是為了**解決瀏覽器性能問題**而被設計出來的。**如前**,若一次操作中有10次更新DOM的動作,虛擬DOM不會立即操作DOM,而是將這10次更新的diff內容保存到本地一個JS對象中,最終將這個JS對象一次性attch到DOM樹上,再進行后續操作,避免大量無謂的計算量。**所以,**用JS對象模擬DOM節點的好處是,頁面的更新可以先全部反映在JS對象(虛擬DOM)上,操作內存中的JS對象的速度顯然要更快,等更新完成后,再將最終的JS對象映射成真實的DOM,交由瀏覽器去繪制。
### 實現虛擬DOM
例如一個真實的DOM元素如下
```html
<p title="段落">這是p標簽</p>
```
```javascript
{
name:'p',
props:{
title:"段落"
},
children:['這是p標簽']
}
```
再來描述下面的一個DOM
```html
<p title="段落">這是p標簽 <span>這是span標簽</span></p>
```
再來描述
~~~html
<p title="段落">這是p標簽 <span>這是span標簽</span></p>
~~~
~~~javascript
{
name:'p',
?props:{
title:"段落"
},
children:['這是p標簽',
{
name:'span',
props:null,
children:[’這是span標簽‘]
}
]
}
~~~
我們來想一個問題 我們之前是p標簽里面有個span標簽,那么我們后面把span標簽刪除后,虛擬dom是如何執行的?
答:
```html
<p title="段落">這是p標簽 <span>這是span標簽</span></p>
```
當刪除單擊按鈕時想要刪除span標簽,不會直接刪除,而是先要生成右側新的(刪除掉span后)的虛擬DOM對象,和左側的虛擬DOM對象作對比,發現只是少了span元素,那么它在操作真實DOM的時候會一次性將之前的span元素刪除。

## Diff算法
* tree diff:新舊DOM樹,逐層對比的方式,就叫做 tree diff,每當我們從前到后,把所有層的節點對比完后,必然能夠找到那些 需要被更新的元素;
* component diff:在對比每一層的時候,組件之間的對比,叫做 component diff;當對比組件的時候,如果兩個組件的類型相同,則暫時認為這個組件不需要被更新,如果組件的類型不同,則立即將舊組件移除,新建一個組件,替換到被移除的位置;
* element diff:在組件中,每個元素之間也要進行對比,那么元素級別的對比,叫做 element diff;
* key:key這個屬性,可以把 頁面上的 DOM節點 和 虛擬DOM中的對象,做一層關聯關系;

參考資料:
https://www.jianshu.com/p/af0b398602bc
[http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html](http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html)
- webpack復習
- React基礎
- 前端三大主流框架對比
- React中幾個核心的概念
- React基礎語法
- React JSX語法
- React組件
- 普通組件
- 組件通信-父向子傳遞
- 組件拆成單個文件
- 面向對象復習
- Class組件基礎
- Class組件的私有狀態(私有數據)
- 案例:實現評論列表組件
- 組件樣式管理
- 組件樣式分離-樣式表
- CSS模塊化
- 生命周期
- React組件生命周期
- Counter組件來學習組件生命周期
- 生命周期總結
- 生命周期案例
- React評論列表
- React雙向數據綁定
- React版todolist
- 其它提高(了解)
- 組件默認值和數據類型驗證
- 綁定this并傳參的三種方式
- 祖孫級和非父子組件傳遞數據(了解)
- React路由
- 路由基礎
- 動態路由
- 路由嚴格模式
- 路由導航定位
- 路由重定向
- 路由懶加載
- WolfMovie項目
- 項目初始化
- AntDesign使用
- 其它相關了解