owned this note
owned this note
Published
Linked with GitHub
---
type: slide
---
## React 思維進化
## 2-4 ~ 2-5
---
## Recap
---
### DOM
```
* 由DOM element組成的樹狀結構,用於表示瀏覽器中的畫面
* 是瀏覽器內建的特殊JS物件,包含該元素的屬性並提供操作方法
* 每當去更動DOM element時,等同於重新渲染實際畫面
```
---
### Virtual DOM
```
* 一種設計概念,Virtual DOM → DOM 同步關係為單向的
* 透過事先定義好的模板程式來產生新的 Virtual DOM
* 與此前最後一次舊畫面用的 Virtual DOM 結構細節比較
* 將新舊的差異的部分更新到實際的 DOM 中, 以完成瀏覽器畫面的更新
* 優點:透過最小範圍的DOM操作,達到效能優化
```

---
### React element
```
* 為React 基於Virtual DOM概念所實現的"虛擬畫面結構元素"
* 為JS物件資料
* 用於描繪一個預期的實際DOM element結構,也為最小組成單位
* 透過React提供的createElement()方法來建立React element
* 經過React處理轉換後,即能自動產生對應的實際DOM element到畫面中
```
```
const reactElement = React.createElement(
'ul',
null,
React.createElement('li', null, 'item1'),
);
```
----
### JSX
```
* React提供的語法糖, 刻意設計類似於HTML語法去建立React element
* 撰寫 JSX 語法 = 撰寫 React.createElement方法的呼叫
* 需搭配透過外部工具(Babel)轉譯成React.createElement方法的呼叫
* 才能正常在瀏覽器環境執行
```
---
## 2-4
### JSX根本就不是在JavaScript中寫HTML
---
* ### 什麼是JSX語法
* ### Babel與JSX語法轉譯的概念
* #### DOM, Virtual DOM, React element, JSX關係概念
---
### 什麼是JSX語法
* React 提供的一種 "語法糖",用於提升程式碼可讀性及開發體驗
* 透過刻意設計模仿"貼近HTML語法", 但本質上和HTML是不同的東西
---
JSX語法 = React.createElement方法的呼叫
```
const reactElement = ( // JSX語法
<ul>
<li>item1</li>
</ul>
);
const reactElement = React.createElement(
'ul',
null,
React.createElement('li', null, 'item1'),
);
```
---
## <font color="cake">But</font>
* JSX是React.createElement方法呼叫的替代語法
* 一段JSX語法為表達一個"值"
=> 呼叫React.createElement的回傳"值"
* 基本上瀏覽器只看得懂三種語言
HTML、CSS 和 JavaScript
* 所以瀏覽器讀不懂JSX
也無法正常在瀏覽器中運作..
那...JSX如何在瀏覽器中正常運作呢?
---
### Solution
執行前用<font color="snake">專門的工具</font>將程式碼靜態轉譯成
"可執行的React.creacteElement呼叫語法" 後,
即可在瀏覽器環境下正常執行。
---
### Babel
JavaScript社群中最主流&熱門的
source code transpiler
---
### Transpiler (轉譯器)
- 將高階語言的程式原始碼轉化成另一種模樣的高階語言程式原始碼, 即做同語言或跨語言的轉換
- 一般瀏覽器無法支援JSX的解讀,在程式原始碼被真正執行前, 先用轉譯器將程式碼進行轉換,再將轉譯後的版本給瀏覽器做執行
---
### JSX tranformer
* 透過不同的plugin來支援不同語法的轉譯效果
* 負責轉譯JSX語法的工具
* @babel/plugin-transform-react-jsx
* 設置上述plugin為JSX transformer
* Babel即能將JSX語法轉譯為React.createElement( )
---
* 上述流程稱為:程式碼的靜態分析與處理
* 尚未實際執行程式碼
* 僅分析純文字及處理相關轉譯、檢查、優化等動作
* 程式碼的<font color="snake">轉換</font>會在 <font color="snake">build time發生及完成</font>
* 程式碼的<font color="snake">讀取及執行</font>會在 <font color="snake">runtime發生</font>

---
### 新版JSX tranformer 與 jsx-runtime
---
### React 17 前
- 必需 `import React from 'react';` 如無會報錯
- JSX transformer會將JSX語法轉為React.createElement( )後輸出
- 在runtime時 JSX transformer已預期有React變數, 及有createElement方法可呼叫
---
### React 17 後
* 官方們合作並支援新的JSX transformer
* 新的JSX transformer & jsx-runtime支援下的優點
- 無須再手動import React
- 略為改善bundle大小
- 其他效能與提示的優化
- 新舊JSX transformer在JSX語法上完全相容
---
### 自動import
* 17前 將JSX語法轉為React.createElement( )呼叫
* 17後 改成提供 jsx-runtime的_jsx( )
取代 React.createElement( )

---
### _jsx( ) 與 React.createElement( ) 的不同
- 相同處
- 用來建立React element的方法
- 透過參數定義想要的React element結構, 並回傳一個React element
- _jsx( ) 的額外優化
- 透過靜態解析JSX語法的語意來避免一些多餘的資料處理流程
---
新版的JSX transformer & jsx-runtime
提供更便利、優化效果更好的JSX實現
---
DOM, Virtual DOM, React element, JSX關係概念

---
### 觀念檢測
- JSX語法的用途是什麼? 其背後的本質為何?
- JSX語法為什麼長得很像HTML語法?
- 什麼是transpiler?什麼是JSX transformer?
- 開發時撰寫的JSX語法是透過哪些流程處理,最後才能順利在瀏覽器執行並定義畫面?
---
## 2-5
### JSX的語法規則脈絡 &
### 畫面渲染的實用技巧
---
### 嚴格標籤閉合
* HTML 具有容錯性
* JSX 是嚴格閉合!
* 若沒有正確閉合,JSX transformer沒有辦法正確解析React.creatElement( )的呼叫及階級,則會產生轉譯失敗的錯誤
```
// 有子元素 => 需有開標籤及閉標籤
const label_1 = <div> 子元素 </div>
// 無子元素 => 可以用"自我閉合方式"簡寫
const label_2 = <img src="./pic.jpg" />
const label_3 = <link rel="stylesheet" href="styles.css" />
```
---
## JSX語法中的資料表達
```
* 可使用類似於HTML語法去建立React element,但本質上是完全不同的
* HTML : 純字串格式的一段靜態文字組成的標籤語言,
不具運算邏輯或資料型別的概念
- 僅能表達標籤結構及固定字串
* JSX : 轉譯後是可執行的JavaScript 執行碼
- 能表達JS中所有資料型別的值 & 能直接使用變數等各種表達式
```
---
## JSX語法中的資料表達
- 表達一段固定的字串字面值
- 表達一段表達式
---
### 詞彙說明
```
* 字面值:表達"固定值"的表示法,
不須進行任何計算操作, 直接出現的固定值
- 數字、字串、布林值、JS中的物件字面值、陣列字面值
* 表達式:"計算產生值"的表示法,
根據變數、運算子、函式的值做變化
- 變數、運算子、函式呼叫及其他表達式
* 都是用來表達和產生值
- 字面值 = 值本身
- 表達式 = 產生"值"的計算過程
```
---
### 表達一段固定的字串字面值
支援使用與HTML相同語法的風格來表達內容
- 指定<font color="snake">屬性值</font>時表達字串字面值
- 雙引號包起來
- 指定<font color="snake">子元素</font>時表達字串字面值
- 將內容寫在開標籤及閉標籤間

---
轉譯輸出後,成為一段字串的字面值

---
### 表達一段表達式
如欲表達<font color="snake">固定的字串字面值以外</font>的表達式,
都需使用JSX指定的語法 <font color="cake">{ }</font> 將表達式包住
- 指定<font color="snake">屬性值</font>時表達一段表達式
- 指定<font color="snake">子元素</font>時表達一段表達式
---
函式、變數、表示式

---
以大括號包起來的表達式程式碼,
會原封不動地放在對應位置

---
### 表達一段表達式
- JSX被轉譯時,會自動拆解開閉標籤間的子元素
- 字串字面值無論多長都會被當成一個子元素
- 每個表達式都為一個獨立的子元素
- 有助於更新時只操作對應的DOM element, 來達到<font color="snake">縮小DOM的操作範圍</font>來降低效能成本。
---
### JSX語法中表達
### 另一段JSX語法作為子元素
```
* 在一段React.createElement 方法的呼叫中,
包含另一段React.createElement方法的呼叫來做為子元素
* React.createElement( )的呼叫屬於表達式的一種,
原理上應該要以{ }包起來
```
 
---
- 但因JSX語法有支援直接在父元素的開標籤與閉標籤間寫上子元素標籤,則可省略{ }

---
* React element <font color="snake">子元素</font> 如何被處理成實際DOM element?
* 當定義一個對應DOM element類型的React element時,其<font color="snake">子元素會根據型別不同</font>而有不一樣的處理方式來被轉換
---
### React element的子元素的支援型別
當各種資料型別作為React element子元素
並轉換到DOM時的處理行為
---
React element, 字串值, 數字值

---
布林/null/undefined, 陣列, 物件, 函式

---
### 畫面渲染邏輯
動態列表渲染 及 條件式判斷渲染
---
### 動態列表渲染
- <font color="cake">陣列型別</font>的子元素<font color="snake">會進行攤開處理,並依序渲染每一個元素</font>
- 適合處理動態資料列表的對應用畫面
- 需加 <font color="cake">KEY</font>值
- React 處理動態列表時,會需要對陣列中的React element 做Virtual DOM的效能優化處理,故會要求在陣列中的每個React element都是唯一、不重複的key屬性
---


---
### 條件式判斷渲染
- 根據資料或狀態作為條件式,來判斷是否要繪製特定畫面區塊
- && 運算式
- 三元運算式
---
### && 運算式說明
```
&&運算子本身的效果:
* 透過 Truthy & Falsy 用來描述一個值在布林型別自動轉換中的行為
* 當運算子左邊的值為"Truthy"時 => 回傳運算子"右邊"的值
* 當運算子左邊的值為"Falsy"時 => 回傳運算子"左邊"的值
( 3 > 1 ) && 'foo' => 'foo' // 左邊為Truthy => 回傳'foo'
( 1 === 2 ) && 'bar' => false // 左邊為Falsy => 回傳False及不印
```
```
- Truthy : 排除屬於Falsy值外的值
- Falsy:
- 布林型別自動轉換的情況下被視為false值
- false, 0, 空字串, null, undefined, NaN
```
---
## 特別注意!!
### 當數字型別的值為0時

---
### 透過&&運算式來進行條件式渲染
- 當(isSuperUser)條件符合時渲染特定畫面,
若不符合則都不印

---
### 透過三元運算式來進行條件式渲染
- a ? b : c
- 當 a 為 true 時,回傳 b,否則回傳 c

---
### 一段JSX語法的<font color="cake">第一層</font>只能有一個節點?
- 一段JSX為呼叫一次React.createElement方法,它只會回傳<font color="snake">一個React element</font>作為結果
- <font color="cake">樹狀資料結構只能有一個根節點</font>
- 解決方式:用<font color="snake">一個共同的父元素</font>將欲放置在同層的多個React Element包起來
 
---
## <font color="cake">BUT</font>
- 為了解決上述問題, 而<font color="snake">多了一層沒有特別意義的元素</font>時...
- 產生多餘的階層而降低可讀性
- 無意義的Dom element恐導致CSS樣式或專案中針對DOM結構所寫的某些邏輯壞掉
 
---
### Fragment
- React提供的內建特殊元素類型
- 藉此建立一個父元素
```
- 使用<Fragment> 需import
- 使用 <> 空標籤 可省略import
```
 
---
不會產生實際的Dom element,
且能作為容器用的的React element

---
### 觀念檢測
- JSX 語法與HTML語法有哪些不同之處?
- 為什麼一段JSX語法的第一層只能有一個節點?
---