Lois Chen
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
--- type: slide --- # Tech Book Community - 《React 思維進化》2-1 ~ 2-3 --- 首先,這是一個人看到的畫面 ![image](https://hackmd.io/_uploads/SJpR5xjsp.png =80%x) ---- 這個畫面由 DOM 組成 ![image](https://hackmd.io/_uploads/rkXcpgjja.png =80%x) --- ## DOM ---- ### 什麼是 DOM ? - 一種樹狀結構,用來表示瀏覽器中的畫面結構 - 一個元素就是一個 DOM element - DOM element 是瀏覽器中內建的特殊 JavaScript 物件 - DOM 與瀏覽器的渲染引擎有著緊密的連動 - 操作大量的 DOM 效能成本昂貴 ---- ### 前端效能優化關鍵: #### 操作最小範圍的 DOM 操作來完成畫面變動 ---- ### 那要怎麼做? ---- ### 另一種畫面更新策略 - 利用自創資料來定義虛擬的畫面結構 - 通常是利用普通的 JavaScript 物件變數來定義 - 模擬並對應實際 DOM 的畫面結構 - 這個概念叫 Virtual DOM - 畫面更新策略是將新版與舊版 Virtual DOM 做結構比較 - 只變動有差異的地方,將實際 DOM 操作範圍最小化 --- ## Virtual DOM ---- ### 什麼是 Virtual DOM ? - 只是一種程式設計概念 - 為了有效處理畫面 UI 設計的 - 概念核心是一種「虛擬的畫面結構」的自創資料 - 本身也是一種樹狀結構 - 每一個元素是自創資料,通常是普通的 JavaScript 物件變數 - 內容嘗試在描述一個實際的 DOM element 預計的樣貌 - 沒有與渲染引擎做直接綁定 - 畫面試作品 ---- ### 畫面更新流程 ![image](https://hackmd.io/_uploads/SJ9R7-oip.png) - 先以 Virtual DOM 形式定義期望的畫面結構 - 再依 Virtual DOM 結構來操作實際 DOM - 使實際 DOM 與 Virtual DOM 結構對應一致 ---- ### 所以 Virtual DOM 比 DOM 快嗎? ---- ### 不,甚至 Virtual DOM 在某些情境下比 DOM 慢 ---- ### 因為人類終究不是機器人,無法「總是」寫出精確又高效的 DOM 操作 - 畫面更新最後一定得操作實際 DOM - 所以如何總是以最小範圍來操作 DOM 是一個思考點 - 因此才有 Virtual DOM 這一解決方案 - 透過虛擬的畫面結構資料比較來異動只需要更新的地方 ---- ### Virtual DOM 的目的不是為了提升效能 - 但某些情境下 Virtual DOM 會比 DOM 慢 - 因為 Virtual DOM 多了一層重新建立以及 Diffing 計算 - 只是 Vitual DOM 確保了人類能夠以最小成本來更新 DOM 操作 - 總的來說,Virtual DOM 的目的不是為了提升效能而是提升開發體驗 --- ## OK 我知道 Virtual DOM 跟 DOM 是啥了 --- ## 那跟 React 的關係是啥? --- ### 首先這是 React 生成的人看的畫面 ![image](https://hackmd.io/_uploads/rJh3rGooT.png) ---- ### 這是用來命令 React 產畫面的程式碼 ![image](https://hackmd.io/_uploads/SJ3hvfsoa.png =80%x) ---- ### 這裡使用了 `React.createElement` ### 用來建立 React element ![image](https://hackmd.io/_uploads/rkGQ5IisT.png) --- ## React element ---- ### 什麼是 React element - 在 React 的實作中 Virtual DOM 畫面結構裡的每個元素稱為「React element」 - 作為描述並組成畫面的最小單位 - React 基於 Virtual DOM 概念所實現的虛擬畫面結構元素 - 是一種普通的 JavaScript 物件資料 - 用於描述一個預期的 DOM element 結構 ---- - React element 是透過呼叫 React 提供的 `createElement` function 來建立 ![image](https://hackmd.io/_uploads/SJ3hvfsoa.png =80%x) ---- ### 若嘗試將其 console.log ![image](https://hackmd.io/_uploads/S1QBufsoT.png =80%x) 會是一個普通的 JavaScript 物件 ---- 把這個 React element 交由 React 進行轉換處理 ![image](https://hackmd.io/_uploads/SJ3hvfsoa.png =80%x) ---- 就可以自動產生對應的實際 DOM ![image](https://hackmd.io/_uploads/rJfYdfsoT.png) ---- ### React element 在建立後不可被修改 - React 基於 Virtual DOM 概念的虛擬畫面結構實作 React element - 是在描述某個時間點版本的畫面結構 - 有畫面更新需求時,產生一份全新的 React element - 新版與舊版 React element 進行比較,只更新有差異的地方 ---- ### 核心機制:新舊比較 React 為了保護新舊 React element 比較的核心機制,而將 React element 實作設計成防止建立後修改,在實際程式中,即使嘗試修改一個已建立的 React element 內容,也會發現毫無效果 ---- ### 那麼,React 是如何把 React element 轉換成實際 DOM element 並繪製在瀏覽器畫面中呢? --- ## Render React element ---- 具體來說 這個流程的概念就是指定瀏覽器畫面中的特定區塊 讓 React 對其擁有完全的管轄權 來持續地進行 Virtual DOM => DOM 的單向轉換與同步化 ---- ### 步驟一:準備一個輸出實際 DOM 結果的目標容器 ![image](https://hackmd.io/_uploads/ryQElDjip.png) ---- ### 步驟二:建立 root 並指定目標容器 - 從此,這個被指定的 root 就是由 React 管轄的 - React 產生並管理 DOM element 輸出結果的畫面渲染管轄入口 ![image](https://hackmd.io/_uploads/Sk0YMvoia.png) ---- ### 步驟三:準備一個用來描述畫面的 React element ![image](https://hackmd.io/_uploads/Hk3rfwooT.png) ---- ### 步驟四:以建立好的 root 來將 React element 繪製成實際的 DOM element - 透過執行 `root.render()` 來將 React element 進行轉換 - 渲染成實際的 DOM element ![image](https://hackmd.io/_uploads/HkQJXPsjp.png) ![image](https://hackmd.io/_uploads/r1_JKql2T.png) ---- ### 一些補充 - React 支援一個前端應用程式中有多個 root 的存在,可以在其他前端解決方案中小範圍使用 React,達到較輕量的整合 - React 不建議直接以 `document.body` 來作為 `createRoot` 的容器 - `createRoot` 是 React 18 以上提供的新 function,在小於等於 17 舊版中,是直接從 ReactDOM 呼叫 `render` ---- ### React element 從概念上來說是在表達某一個歷史時刻當時的畫面 - React element 一旦被建立之後就永遠不能再被修改 - 有畫面更新需求時,應當再建立一份全新的 React element - 如此才有可靠的歷史紀錄 - 作為新舊版本 Virtual DOM 的比較機制的資料依據 ---- ### React 只會去操作那些真正需要被更新的 DOM element - 有畫面更新需求時而產生新的 React element,並交由 `react-dom` 處理之後 - React 會自動進行新舊 React element 的樹狀結構比較 - 並只操作這些差異之處所對應的實際 DOM element ---- ### 比較新舊 React element 的差異以及最小化 DOM 操作,都是由 React 自動完成的工作 因此,以 React 開發時的效能優化關鍵,其實會是在 - 避免不必要時的 React element 產生動作 - 在部分畫面沒有更新需求時重用舊有的 React element ---- ### Virtual DOM 概念另一好處 - Virtual DOM 除了優化 DOM 操作效能之外 - 另一個好處是能夠將畫面管理流程分離兩個獨立階段來處理 - Reconciler:定義以及管理畫面結構描述 - Renderer:將畫面結構的描述繪製成實際畫面成品 ---- ### Reconciler - 在能夠跑 JavaScript 的環境中通用 - 負責定義以及管理畫面結構描述 - 在瀏覽器環境中的實際處理: - 定義並產生新的 React element 來描述預期的 DOM 結構 - 在畫面有更新需求時將新舊 React element 比較差異之處,並交給 render 進行處理 ---- ### Reconciler - 定義並產生新的 React element 來描述預期的 DOM 結構 ![image](https://hackmd.io/_uploads/Hk3rfwooT.png) ---- ### Renderer - 可以被任意替換 - 只要有支援其他目標的 renderer 配合 - React 也可以用於管理並產生瀏覽器 DOM 以外的 UI 或畫面 - 負責將畫面結構的描述繪製成實際畫面成品 ---- ### Renderer - 在瀏覽器環境中的實際處理: - 用於瀏覽器環境的 renderer 就是 `react-dom` - 將 React element 透過 `react-dom` 產生的 root,在瀏覽器環境中繪製成實際的 DOM - 在畫面有更新需求時,將 reconciler 已經比較出來的新舊 React element 差異之處,同步化到實際的 DOM 更新與操作 ---- ### Renderer - 將 React element 透過 `react-dom` 產生的 root,在瀏覽器環境中繪製成實際的 DOM ![image](https://hackmd.io/_uploads/HkQJXPsjp.png) ![image](https://hackmd.io/_uploads/r1_JKql2T.png) ---- ### Reconciler 與 Renderer 的實際應用 ![image](https://hackmd.io/_uploads/BkIHcienT.png) ---- ### 關於 Reconciler 與 Renderer 的補充資料 - [awesome-react-renderer](https://github.com/chentsulin/awesome-react-renderer) - [Build your own React renderer](https://www.youtube.com/watch?v=CGpMlWVcHok) --- ## Recap ---- ### DOM 瀏覽器的畫面是由 DOM 組成,但因為 DOM 直接連動瀏覽器引擎,若 DOM 操作不夠精確,會導致更新大範圍而造成效能成本昂貴最後形成畫面卡頓影響使用者體驗 ---- ### Vritual DOM & React element 因此 React 採用 Virtual DOM 的概念來實作 React element,其本身是一個普通的 JavaScript 物件變數,並且不直接與瀏覽器引擎綁定,當有畫面需求更新時,React 採用了 Virtual DOM 的畫面更新策略比較新舊機制,先產一份全新的 React element 來與舊版 React element 做結構比較後只更新有差異的部分,來避免效能的過度花費 ---- ### Render element React 將 React element 轉換成實際 DOM 並繪製到瀏覽器畫面中的流程需要先準備一個輸出實際 DOM 結果的目標容器,並建立 root 指定目標容器,將該容器指定 React 擁有完全的管轄權,而後準備一個用來描述畫面的 React element,最後以建立好的 root 來將 React element 繪製成 DOM element 注入到目標容器中 ---- ### Reconciler & Renderer Virtual DOM 除了優化 DOM 操作效能之外,另一個好處是能夠將畫面管理流程分離兩個獨立階段來處理 - Reconciler:在能夠跑 JavaScript 的環境中通用,負責定義以及管理畫面結構描述 - Renderer:可以被任意替換,負責將畫面結構的描述繪製成實際畫面成品 這樣分離的好處是能夠與平台解耦,最後達到 React 官方所宣稱的「Learn once, write anywhere」效果

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully