# 2-6_單向資料流、一律重繪渲染策略
## 2-6-1_單向資料流
---
### 【資料驅動畫面】
- 單向資料流
- `one-way dataflow`
- 現代主流框架的設計模式( design pattern)
---

- 畫面結果 = 原始資料透過模板 + 邏輯所產生的延伸結果
- 單向
- 不可逆
- 只有當資料更新時,畫面才會更新
- 不能在相關的資料更新以外的情況被修改
---
### 【資料與畫面的分離管理:單一資料來源】
- 將資料管理與畫面渲染進行分開處理,並獨立定義
---
- 不獨立定義原始資料
- 直接操作 DOM,反映使用者的行為
- 難以保證資料的完整與一致
- 資料與畫面分離
- 更新原始資料,反映原始資料的變化
- 提高資料的穩定與可靠
---
- 單一資料來源
- `Single source of truth`
- 只有源頭的原始資料才是畫面的來源
- 同個概念的資料不應該在多個地方存在
---
### 【限縮變因的價值】
- 畫面不會因為資料變化以外的任何原因而隨意改變
- 資料變動
- 開發者的手動觸發資料更新
- 畫面結果
- 原始資料
- 模板邏輯
---
- 價值
- 提高可維護性
- 提升可讀性
- 減少資料意外出錯
- 更好的效能
---
## 2-6-2_實現單向資料流的 DOM 渲染策略
---
### 【策略一:當資料更新後,人工判斷並手動修改所有應受到連動更新的 DOM element】
```javascript!
function incrementCounterAndUpdateDOM(index) {
counterValues[index] += 1;
// 資料更新後,需要具體知道這次資料的更新會影響到的 DOM 範圍,並且手動一一去更新:
// 修改某個 counter 的 value 資料後,
// 該 counter 對應的 <li> 裡面的 <span> 的文字內容會需要更新
document
.querySelectorAll('#counter-list > li > span')
.item(index)
.textContent = counterValues[index];
// 修改某個 counter value 資料後,也會需要重新計算並更新 counter sum 的文字內容
document
.querySelector('#counter-sum > span')
.textContent = getNumbersSum(counterValues);
}
```
> <https://codesandbox.io/s/96fzf5>
---
- 只手動操作資料更新時,會影響到的 DOM element

---
- 好處:
- 只要開發者 DOM 操作得夠簡潔精準,可以減少因為多餘 DOM 操作造成的效能浪費
- 風險:
- 仰賴開發者的人為判斷、以及對 DOM 的精確手動操作
---
### 【策略二:當資料更新後,一律將整個畫面的 DOM element 全部清除,再以最新的原始資料來全部重繪】
```javascript!
// 每次要繪製新的畫面之前,都先把整個瀏覽器畫面全部清空
document.body.innerHTML = '';
```

> <https://codesandbox.io/s/ke7msp>
---
- 好處:
- 只要將資料、模板定義好,當資料更新後都會一律重新繪製畫面
- 缺點:
- 效能浪費
---
### 【總結:整理一下以上 2 種渲染策略的優缺點】
| | 優點 | 缺點 |
| -------------------------- | -------------------------------------------------- | ------------------------ |
| 策略一:手動更新對應的 DOM | 只要開發者的 DOM 操作夠精準,就能減少效能浪費 | 仰賴人為判斷,非常困難 |
| 策略二:一律重繪 | 開發者只需要關注模板定義、資料更新的處理,直覺簡單 | 會有多餘不必要的 DOM 操作而影響效能 |
---
### 【前端框架的處理策略】
- 不論何種策略,都有明顯的缺點
- 資料更新後的畫面連動更新
- 大多數的前端框架可以 **同時保留優點並解決缺點**
---
- Vue.js
- 策略一
- 追蹤資料與模板的綁定關係,監聽資料去更新畫面
- React.js
- 策略二
- 一律重繪
---
## 2-6-3_React 中的一律重繪渲染策略
- 既然一律重繪很浪費效能,那就改成一律重繪虛擬的畫面結構資料,也就是 React element
- Virtual DOM 只是普通的自訂變數資料
- 不像 DOM 會與瀏覽器引擎綁定
---
- React render:
- 產生 React element 的流程
- React re-render:
- 重繪 React element 的流程
- 以新的原始資料重新產生新版的 React element
- 「以新的資料(props 或 state)重新再執行一次 component function,並產生新版的 React elements」
---
- React 會以 component 作為一律重繪的切分單位
- 當我們呼叫一個 state 的 setState 方法時,React 就只會重繪該 state 所屬的 component 以及它底下的所有子孫 components,而不會整個 App 都重繪
---
## Review
---
### 單向資料流是什麼
---
### 實現單向資料流的策略有哪些?分別的優缺點為何?
---
### React 為了維護單向資料流所採用的策略是什麼?以及是如何解決缺點的?
---
## Reference
> 《React 思維進化:一次打破常見的觀念誤解,躍升專業前端開發者》-2024
> <https://www.tenlong.com.tw/products/9786263337695>
>
> 《[Day 09] 單向資料流 & DOM 渲染策略》-2023
> <https://ithelp.ithome.com.tw/articles/10296750>
>
> 《[Day 10] React 畫面更新的核心機制(上):一律重繪渲染策略》-2023
> <https://ithelp.ithome.com.tw/articles/10298007>
---
## Q
- `one-way data flow`
```markdown!
This is called one-way data flow because the data flows down from the top-level component to the ones at the bottom of the tree.
```
> <https://react.dev/learn/thinking-in-react>
---
{"contributors":"[{\"id\":\"24187e66-a778-4778-a2dc-98f9cdf79fe0\",\"add\":3528,\"del\":47}]","description":"","title":"2-6_單向資料流、一律重繪渲染策略","image":"https://hackmd.io/_uploads/HJPUNr4Ap.jpg"}