I LUN
    • 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 --- ## React 思維進化 ## 2-4 ~ 2-5 --- ## Recap --- ### DOM ``` * 由DOM element組成的樹狀結構,用於表示瀏覽器中的畫面 * 是瀏覽器內建的特殊JS物件,包含該元素的屬性並提供操作方法 * 每當去更動DOM element時,等同於重新渲染實際畫面 ``` --- ### Virtual DOM ``` * 一種設計概念,Virtual DOM → DOM 同步關係為單向的 * 透過事先定義好的模板程式來產生新的 Virtual DOM * 與此前最後一次舊畫面用的 Virtual DOM 結構細節比較 * 將新舊的差異的部分更新到實際的 DOM 中, 以完成瀏覽器畫面的更新 * 優點:透過最小範圍的DOM操作,達到效能優化 ``` ![image](https://hackmd.io/_uploads/SJLcg9gTp.png) --- ### 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> ![buildtime](https://hackmd.io/_uploads/Syb4pU33T.jpg) --- ### 新版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( ) ![image](https://hackmd.io/_uploads/r1N7Zueaa.png) --- ### _jsx( ) 與 React.createElement( ) 的不同 - 相同處 - 用來建立React element的方法 - 透過參數定義想要的React element結構, 並回傳一個React element - _jsx( ) 的額外優化 - 透過靜態解析JSX語法的語意來避免一些多餘的資料處理流程 --- 新版的JSX transformer & jsx-runtime 提供更便利、優化效果更好的JSX實現 --- DOM, Virtual DOM, React element, JSX關係概念 ![2-4-5](https://hackmd.io/_uploads/HJ1Fr6W6p.png) --- ### 觀念檢測 - 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>時表達字串字面值 - 將內容寫在開標籤及閉標籤間 ![image](https://hackmd.io/_uploads/r19yJKn26.png) --- 轉譯輸出後,成為一段字串的字面值 ![image](https://hackmd.io/_uploads/HyaAkKhhT.png) --- ### 表達一段表達式 如欲表達<font color="snake">固定的字串字面值以外</font>的表達式, 都需使用JSX指定的語法 <font color="cake">{ }</font> 將表達式包住 - 指定<font color="snake">屬性值</font>時表達一段表達式 - 指定<font color="snake">子元素</font>時表達一段表達式 --- 函式、變數、表示式 ![image](https://hackmd.io/_uploads/HkNqdYhnT.png) --- 以大括號包起來的表達式程式碼, 會原封不動地放在對應位置 ![image](https://hackmd.io/_uploads/HkZxtK23a.png) --- ### 表達一段表達式 - JSX被轉譯時,會自動拆解開閉標籤間的子元素 - 字串字面值無論多長都會被當成一個子元素 - 每個表達式都為一個獨立的子元素 - 有助於更新時只操作對應的DOM element, 來達到<font color="snake">縮小DOM的操作範圍</font>來降低效能成本。 --- ### JSX語法中表達 ### 另一段JSX語法作為子元素 ``` * 在一段React.createElement 方法的呼叫中, 包含另一段React.createElement方法的呼叫來做為子元素 * React.createElement( )的呼叫屬於表達式的一種, 原理上應該要以{ }包起來 ``` ![image](https://hackmd.io/_uploads/ryh4wch2p.png) ![image](https://hackmd.io/_uploads/S1zvwq23T.png) --- - 但因JSX語法有支援直接在父元素的開標籤與閉標籤間寫上子元素標籤,則可省略{ } ![image](https://hackmd.io/_uploads/BykKP932p.png) --- * React element <font color="snake">子元素</font> 如何被處理成實際DOM element? * 當定義一個對應DOM element類型的React element時,其<font color="snake">子元素會根據型別不同</font>而有不一樣的處理方式來被轉換 --- ### React element的子元素的支援型別 當各種資料型別作為React element子元素 並轉換到DOM時的處理行為 --- React element, 字串值, 數字值 ![image](https://hackmd.io/_uploads/Byva01R2p.png) --- 布林/null/undefined, 陣列, 物件, 函式 ![image](https://hackmd.io/_uploads/HJ08IT-aT.png) --- ### 畫面渲染邏輯 動態列表渲染 及 條件式判斷渲染 --- ### 動態列表渲染 - <font color="cake">陣列型別</font>的子元素<font color="snake">會進行攤開處理,並依序渲染每一個元素</font> - 適合處理動態資料列表的對應用畫面 - 需加 <font color="cake">KEY</font>值 - React 處理動態列表時,會需要對陣列中的React element 做Virtual DOM的效能優化處理,故會要求在陣列中的每個React element都是唯一、不重複的key屬性 --- ![image](https://hackmd.io/_uploads/HyiDyZC26.png) ![image](https://hackmd.io/_uploads/B1jSyWCnT.png) --- ### 條件式判斷渲染 - 根據資料或狀態作為條件式,來判斷是否要繪製特定畫面區塊 - && 運算式 - 三元運算式 --- ### && 運算式說明 ``` &&運算子本身的效果: * 透過 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時 ![image](https://hackmd.io/_uploads/S1KB80-p6.png) --- ### 透過&&運算式來進行條件式渲染 - 當(isSuperUser)條件符合時渲染特定畫面, 若不符合則都不印 ![image](https://hackmd.io/_uploads/BJO5oSJaa.png) --- ### 透過三元運算式來進行條件式渲染 - a ? b : c - 當 a 為 true 時,回傳 b,否則回傳 c ![image](https://hackmd.io/_uploads/rye3YH16a.png) --- ### 一段JSX語法的<font color="cake">第一層</font>只能有一個節點? - 一段JSX為呼叫一次React.createElement方法,它只會回傳<font color="snake">一個React element</font>作為結果 - <font color="cake">樹狀資料結構只能有一個根節點</font> - 解決方式:用<font color="snake">一個共同的父元素</font>將欲放置在同層的多個React Element包起來 ![image](https://hackmd.io/_uploads/BJN-OMgaT.png) ![image](https://hackmd.io/_uploads/S1IRvzeTp.png) --- ## <font color="cake">BUT</font> - 為了解決上述問題, 而<font color="snake">多了一層沒有特別意義的元素</font>時... - 產生多餘的階層而降低可讀性 - 無意義的Dom element恐導致CSS樣式或專案中針對DOM結構所寫的某些邏輯壞掉 ![image](https://hackmd.io/_uploads/ryDLeSxa6.png) ![image](https://hackmd.io/_uploads/HyUJyrxa6.png) --- ### Fragment - React提供的內建特殊元素類型 - 藉此建立一個父元素 ``` - 使用<Fragment> 需import - 使用 <> 空標籤 可省略import ``` ![image](https://hackmd.io/_uploads/HJ8YX8JTp.png) ![image](https://hackmd.io/_uploads/SkW6mLJ66.png) --- 不會產生實際的Dom element, 且能作為容器用的的React element ![image](https://hackmd.io/_uploads/SkX5yrgTT.png) --- ### 觀念檢測 - JSX 語法與HTML語法有哪些不同之處? - 為什麼一段JSX語法的第一層只能有一個節點? ---

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