前言
- 學習目標:整理React.js(17)作為前端框架,與Native JS相比增加的常用概念
- 概念建立後,實作的部分再查文件(沒有概念的話,看不懂甚至不知道要查什麼文件)
因為不喜歡Vue的模板與專有語法,覺得很不JS想跳槽- 算是給自己看的讀書筆記、重點整理
- 也可以一邊思考新技術是為了解決那些既有問題
有餘力的話再整理個Vue3的版本
- 簡述React的特色:用JavaScript的思維與格式處理前端的渲染
- 主要的HTML內容改寫在.js檔案(雖然實際格式為JSX),甚至CSS也能選用JS管理
- 只需要一個.html檔案,除了
<head>
的設定,<body>
只需要<div id="root"></div>
給React渲染用 - 使用Virtual DOM的概念一次性的渲染,而非每次個別操作DOM
- 多一些非原生的語法(如render),但看起來風格至少很JS(如和Vue相比?)
- 因為都放在JS處理,有些原生的寫法得改掉(如避免與保留的關鍵字衝突、符合JS的coding style常規)
- 主要參考資料:
- 可先看先前整理的入門篇筆記
- React繁體中文官網
- 有完整文檔和示範教學,但更適合當文件查詢
- 示範教學因為用的是舊的class component,要跟著做的話較推薦下一本書的範例
- 從Hooks開始, 讓你的網頁React起來(2020)
- 改編自鐵人賽系列文章,有JS基礎就能讀懂
- 以專案進度逐步引導用到的React概念(初學者推薦)
- React思考模式:從hook入門到開發實戰(2021)
- 介紹的React功能相對前者較多,且解釋較多運作的原理(需較多先備知識+論述可能較抽象?)
- 補上前一本書最後只是帶到沒有細述的部分,但因為後半較複雜,初次讀先大概看過即可(需實作時再查套件文件比較好用)
- 之前參與協作React.js與React Native(RN,二者簡易轉換心得)專案經驗
- 補充在本文的個人觀點
基礎部分
- 以網頁組成三大元素,個別簡易說明在React多了哪些變動
- 如果是RN,得使用專為RN設計的語法和套件
- 寫的不是HTML和CSS,容易出現WEB沒有的概念
- 加上兼顧不同平台效果(Android、iOS…)的話還有個別設定
基礎安裝設定
- 簡易版(練習,CDN)
- 複雜版(開發,NPM)
- 新建專案時建議用如Create React App等工具產生
- 已有基本套件、結構與設定的專案,改起來比較快
- RN:請從環境建置開始
HTML:寫法的變化(微調的概念?)
寫的其實是JSX而非純HTML(JSX語法其實非React專用,Vue也可以用)
- class => className(與JS保留的關鍵字衝突)
- 表單(form)如input、textarea、select中value屬性概念的變化
- value
- 在React中,值可以選用狀態(state)管理
- 新屬性defaultValue:輸入欄位只有一開始受狀態影響的初始值
- 既有寫法:欄位數值一直受狀態管理(不像純HTML只定義初始值)
- checked
- 可用回傳布林值設定
- value
- kebab case => camel case
- 寫法習慣,如在JS寫CSS/RN的style,否則噴錯誤
- 一些原本沒用kebab的也要改camel,如onclick => onClick
- html作為特殊資料類型而非字串)(render()使用)
"<div></div>"
=><div></div>
- component(元件/組件,格式:
<Component />
或<Component>...</ Component>
)- 大寫開頭,以和一般的HTML作區別
- 除了自己寫,也可以引入套件(再參考文件說明的屬性使用)
- 使用**Design System (設計系統)**:如Ant Design、Material UI…,比bootstrap更進階的懶人救星(X)
- 最外層一定要包一個Tag
- 僅包覆不含語意的寫法:Fragment(
<></>
)
- 只要大概了解JSX與純HTML的差別部分,以及有component的概念,即使沒學過React才有的JS語法,就能以既有的概念切版,甚至多少看懂functional component 的用途(個人想法)
- 略懂就能寫React(X)可以協助較簡單的部分(O)
CSS:格式的選擇性(不一定要大改)
格式可以和純靜態檔案一樣,或加上JS擴充大改
- 主要考量:分拆管理、避免全域衝突…
- 可考慮用原生CSS以外的工具,以加入更多程式邏輯要素(如嵌套、變數、運算):
- 常見工具方案與原生寫法的簡易比較
Script – 1:加入React才有的常見概念
基本符合JS風格下,新增若干概念和語法
render()
:頁面用JS設定後才一起渲染,而非個別修改DOM- key:辨認同類元件的索引,重複渲染元件時若沒設定會跳警告
${}
vs{}
/{{}}
${}
:原生語法的樣板字面值/模版字符串(template literal){}
:填React props帶入的資料,或是條件轉譯的判斷式(表達/表示式,expression,有回傳值的邏輯運算做為顯示資料)- 例如切換視圖:{currentPage === ‘SomePage’ && (<Component />)}
{{}}
:填寫CSS/Style屬性(作為物件放到前者的概念)
- function components
- 語法特點
- 以函式(function)形式定義參數屬性與回傳的HTML內容
- 主要取代2019年前較複雜的class components
- 也替代處理資料與畫面對應變動的原生語法(querySelector或getElementByClass/Id後修改DOM)
- 也有生命週期(lifecycle)的概念(類似Vue)
- 分3(+1)階段:初始化/創建/掛載(mounting)、更新(updating)、移除/銷毀/卸載(unmounting),(以及JS噴錯的Error Handling)
- 在class components比較重要,function components較少直接用到
- (個別週期的細節太多人介紹,自行找幾篇來看即可)
- props(概念)
- 引入父層的資料(父傳子)
- 父層資料變動時,子層元件也會重新轉譯(更新資料渲染)
- 如同一般函式,需有引入/回傳相關的值
- 可使用解構賦值來接收(如參數填入
{value}
) - 如果元件層次較多(二三層以上),甚至有傳給同層甚至父層的需求,有Global state的概念比較方便(類似全域變數?)
- Context(概念)
- Global state在React的實作方案
- 建立全域資料:
React.createContext()
- 產生物件,可獨立成外部模組檔案引用(如放context資料夾)
- 使用全域資料:
<XxxContext.Provider>
- 以元件形式引入,屬性加上
value={{context檔案的物件資料/動作格式: 要讓全域使用的變數資料/動作名稱}}
(搭配useState) - 在其他地方使用時,需要使用useContext這個hook
- 數值更新時,有引入的元件會強制渲染(可能影響效能)
- 以元件形式引入,屬性加上
- Hooks(常用)
- 格式:
useSomething
- 其實也算JS的函式(function)
- 在元件內處理資料常用:使畫面變更/變更後執行
- 通常不會在迴圈、條件判斷、槽狀結構等「不一定會執行到」的情況使用
- 最常用於資料存取的hooks
- useState(狀態):定義資料預設內容(
value
)與修改動作(setValue
)- 常以解構賦值定義(如
const [value, setValue] = useState("default")
) - 代替使用變數
var/let
的原生寫法來管理 - 檢查到狀態變更後重新渲染DOM
- 資料與畫面需透過
setValue
的形式修改與渲染,否則無效或噴錯誤(不要用原生的變數寫法來處理,可能值改了但畫面沒改) - 會一次覆蓋全部,只改部分需加入
...value
保留其他資料 - 函式呼叫後其實不會馬上修改state,需要立即接續其他動作的話要用下面的useEffect
- 常以解構賦值定義(如
- useEffect(副作用):畫面渲染後才執行的動作
- 第一個參數,用來定義在畫面更動後的函式,例如:
- 呼叫API存取遠端資料(避免非同步事件阻塞,回傳後再替代載入圖示)
- 外來可能有專門的suspense來處理
- 使用非React專用的外部函式庫(避免衝突)
- 操作DOM、動畫(避免在前面HTML尚未生成)
- add/removeEventListener(建立時add,第一個參數回傳時remove避免重複監聽)
- set/clearInterval(原理同上)
- 呼叫API存取遠端資料(避免非同步事件阻塞,回傳後再替代載入圖示)
- 第二個參數,須定義dependencies,可避免陷入更新資料後,又因畫面隨資料變動陷入迴圈(如用空陣列表沒有要觀察的變動)
- 未定義時,元件建立與每次更新都觸發
- 定義空陣列時,元件建立時才觸發
- 若第一個參數的副作用定義區,使用了沒在第二個相依參數的props/state,會有非預期錯誤
- 第一個參數,用來定義在畫面更動後的函式,例如:
- useState(狀態):定義資料預設內容(
- 存取不受React管理的部分
- useRef:定義的變數可類比直接用原生語法操作DOM元素,而不出現錯誤或React更新渲染
- 括號放預設值,在元件的ref屬性填入使用
- 可用在不需保存狀態的變數、操作特定DOM(新增或移除函式)、用狀態管理可能額外動作的情況(如計數counter、有設定effect副作用)
- 和直接定義全域變數的差別:後者會在重新渲染時更新,導致數值不如預期
- 介於被React管與不管之間(?)
- useRef:定義的變數可類比直接用原生語法操作DOM元素,而不出現錯誤或React更新渲染
- 格式:
- 語法特點