## React 思維進化讀書會
---
Evan
- 非本科轉職(食品科學系畢業)
- Alpha camp
- 前端工程師
- 一年 Angular 開發經驗
---
#### 2-1 DOM 與 Virtual DOM
#### 2-2 建構畫面的最小單位:React element
#### 2-3 Render React element
---
2-1 DOM 與 Virtual DOM
---
### DOM 是什麼?
- 一種樹狀結構資料,用來表示畫面中的結構元素
- 一個元素就是一個 DOM element
- DOM element 是瀏覽器中的特殊 JavaScript 物件
- 與瀏覽器的渲染引擎有著緊密的連動
- 對 DOM 操作時渲染引擎將會自動重新繪製畫面
- 操作 DOM 效能成本昂貴
----
DOM (Document Object Mode)

<!-- 圖片來源:https://hsuchihting.github.io/javascript/20200615/1316819935/ -->
----
前端效能優化的關鍵 --
以「操作最小範圍的 DOM 來完成畫面所需的變動」
----
## Virtual DOM
- 是一種程式設計概念,以「虛擬的畫面結構」資料來模擬期望的 DOM 畫面結構
- 與實際 DOM 保持對應關係
- 畫面結構同步化方向:
Virtual DOM => 實際 DOM
- JavaScript 物件,內容在描述期望的 DOM 結構樣子,本身也是樹狀結構的資料
----
#### Virtual DOM

----
#### 實際 DOM

----
### 畫面更新策略
Virtual DOM 是試做品,DOM 是成品
1. 「完整」產生新的對應畫面的 Virtual DOM 結構
2. 比較新版的 Virtual DOM 跟舊版的 Virtual DOM 之間的差異
3. 兩者差異即為本次更新「真正需操作 DOM 的部分」
4. 「操作最小範圍的 DOM 來完成畫面所需的變動」
----

----
### 畫面更新策略
- 找到「最低成本的 DOM 操作範圍」來達到效能上的優化
- Virtual DOM 的畫面結構資料並沒有與瀏覽器渲染引擎直接的綁定
- 產生、比較新舊版 Virtual DOM 也是會產生效能成本
- Virtual DOM 畫面結構的產生 & 比較都只是 「JavaScript 物件資料」因此在大範圍的變動還是相對的能帶來優化效能的效果。
----
#### 觀念檢測
1. DOM 是什麼? 為什麼操作 DOM 是一種效能成本昂貴的操作?
2. Virtual DOM 是什麼? 與 DOM 的關係是?
3. Virtual DOM 為什麼可以幫助解決頻繁或大範圍的畫面變動時帶來的效能浪費?
---
#### 2-2 建構畫面的最小單位:React element
---
## React element
----
## React element?
- React 基於實踐 Virtual DOM 概念所實作的虛擬畫面結構元素
- 是一種JavaScript 物件,用於描述預期的 DOM element 樣子
- 在 React 中實做的 Virtual DOM 畫面結構裡的每個元素都稱為「React element」
----
### React element
- Virtual DOM 畫面結構中的其中一個元素
- 轉換成 DOM element 只是普通的 JavaScript 物件
---
### React element: 描述畫面的最小單位
- component:
- 非畫面最小單位
- 資料狀態與畫面更新機制的最小切分單位
- 可重用的畫面區塊,由數個 React element 組成
----
#### createElement
- 建立 React element 的方法
單一 React element:

----
#### React element 也可以是巢狀的樹狀結構

----
#### 轉換後,實際 DOM
<img height='450px' src="https://hackmd.io/_uploads/Symc5f8Oyg.png"/>
----
#### 為什麼 React element 建立之後就不可修改?
- Virtual DOM 的概念在 React 實作中就是 React element 來實踐,用來「描述某個時間點版本的畫面結構」
- 比較新舊版 Virtual DOM 的差異,找出實際應該被更新的部分
- React 保護核心運作機制,因此不允許修改已建立的 React element
---
#### React element 與 DOM Element 屬性對應性差異
- attribute & property 改以 camel case 命名:
- onclick ⇨ onClick
- inline styles 的 style 屬性內容格式不同:
- HTML style 字串 ⇨ 物件形式表示
```
style="border: 1px solid red;"
```
```
style={{border: '1px solid red'}}
```
- JavaScript 保留字:
- class ⇨ className
- `<label>` for 屬性 ⇨ htmlFor
---
#### 觀念檢測
1. React element 是什麼? 與 Virtual DOM 的關係為何? 與實際 DOM 的關係為何?
2. 為什麼 React element 一旦被建立後就無法被修改?
---
#### 2-3 Render React element
----
#### React DOM 與 root
<!-- #### React 是如何把 React element 轉換成實際 DOM element 並且重繪製到畫面上的? -->
----
### Virtual DOM 轉換成 DOM 的過程
「指定瀏覽器畫面的特定區塊,讓 React 對其有管轄權.
以持續進行 Virtual DOM => DOM 的單向轉換與同步化的過程」
----
#### 一. 準備輸出實際 DOM 結果的容器

----
#### 二. 建立 root 並指定目標容器

----
#### 三. 準備描述畫面的 React element

----
#### 四. 以建立好的 root 將 React element 轉換成實際的 DOM

----
#### 畫面結果
React element 產生的 DOM element 被注入至指定的目標容器內

----
#### 補充說明(1)
1. 若 root 容器含有非 React 產生的 DOM 內容會怎麼樣?
Ans: 會被 React Element 產生的 DOM element 覆蓋掉
2. root 只能有一個嗎?
Ans: 可以有多個,但在 SPA 的應用程式建議用一個 React root 管裡
----
#### 補充說明(2)
3. 為什麽不能直接用 `document.body ` 作為 root 容器?
Ans: 因許多第三方套件會對 body 操作或修改,會造成 React 對 DOM element 控制管理不穩定
----
#### React 只會操作真正需要被更新的 DOM element
- 新的 React element 產生之後,交由 React-dom 處理
- 比較新舊 React element 的結構差異之處,只更新差異處的 DOM element
----
#### 因此,使用 React 開發時的效能優化關鍵:
1. 避免不必要的 React element 產生動作
2. 部分畫面沒有更新需求時,重用舊有的 React element
開發者只需要著重於 React element 管理
----
#### 重繪製畫面管理流程:Reconciler 與 renderer
- Reconciler:
- 定義&產生新的 React element
- 比較新舊 React element 差異之處
- 負責找出 UI 變更,確定哪些部分需要更新。
- Renderer:
- 將畫面描述的結構繪製成實際的 DOM
- 將在 reconciler 階段比較完畢的新舊差異之處,同步至實際的 DOM
----
#### 分成兩階段處理的好處是什麼?
- 解耦 UI 計算與實際渲染,不依賴特定渲染方式
- 不同環境可以共用 Reconciler,而 Renderer 可以彈性替換成其他環境的 UI 畫面
- 「learn once write anywhere 」
- 其他 Renderer: react-dom、React Native
----
#### 觀念檢測
1. `react-dom` 是什麼? Root 是什麽?
2. 解釋 React DOM 繪製成實際 DOM 的流程以及每個步驟的意義
3. React 怎麽做到只操作那些需要被更新的 DOM element?
4. React 將「定義以及管理畫面結構的描述(reconciler)」和「將畫面結構描述製成實際畫面成品(renderder)」拆分成兩階段處理,這樣設計有什麼好處?
---
#### 討論 Q&A
---
#### 感謝聆聽
---
#### 2/18
- 導讀人
- 筆記工
{"description":"自我介紹","title":"React 思維進化 2-1~2-3","contributors":"[{\"id\":\"8c1b4838-86f3-430e-9300-fea6810bc261\",\"add\":8670,\"del\":3263}]"}