React Basic
用戶建構使用者介面的JavaScript庫
運行在瀏覽器端,非伺服器端:數據變化立即響應
一個React應用由多個React組件互相嵌套建構而成
- header
- content
- footer
- sidebar
ReactJS → JavaScript 庫、渲染HTML
React Native → mobile 程式
在React中,建構一個component可以是一個class或是function的形式
把 component 直接當成 func 來想像,對我來說比較好理解
React重要概念
Virtual DOM 虛擬樹狀結構
React最大的核心在於,它是操作 VD(Virtual DOM) ,再讓 VD 跟 Real DOM 比對,有不同地方就讓 DOM 該部分重新渲染,而不是整個結構都重新渲染,效能影響很大。React 背後會自己生成一個 VD(以JS物件來模擬DOM的結構),是我們看不見的,活在 React 的 memory。
我們肉眼可見的都是DOM!
Virtual DOM的優勢不在於單次的操作,而是在大量、頻繁的數據更新下,能夠對視圖進行合理、高效的更新。
使用 Virtual DOM 最大的優點就是效能,傳統 diff 運算的時間複雜度為 O(n³),使用 Virtual DOM後的 diff 運算為 O(n),不過這不代表所有狀況 Virtual DOM 都會比操作 Real DOM 快速,但可以確保在普遍狀況下,都能有不錯的效能。
單向資料流
只能由父往子層傳 遞,最多應用是父層組件把自己的state傳給子層,作為子層的props,子層可以把自己的props再往下傳給(孫?)子層 → 形成多層的單向資料流
parent & child component: 無論是 class-based 還是 functional 的component,一旦父元件重新渲染,理論上子元件的 render 都會被重新觸發。
基本操作
(若有使用外部的)引入組件、套件 → 定義組件 → 輸出組件
可以把每個組件都想成是一個新的 HTML 的 tag,這個 tag 裡頭已經包著由很多傳統的 HTML tag 所寫成的區塊
import React, {useState} from 'react'; // 引入套件
const MyList = () => { // 定義組件
return (
<div className="App">
My first react!
</div>
);
};
export default App // 輸出組件
// 定義組件的部分 組件開頭通常會是大寫 為了在JSX引入的時候與html的標籤區隔
// 在檔案命名的部分也會是大寫 例如 MyList.js
-------------------
import MyList from './Components/MyList'; //綠色的MyLsit是一個js檔
const App = () => {
return(
...
)
}
JSX
一種以 js 寫成的類 HTML 格式,需要經過編譯才能在瀏覽器呈現
一般的 HTML 你可以很清楚地看出 一個div 他的 class 以及他的內容
但如果用JS原生語法大概要寫成下面這樣
React.createElement( 'div' ,{class:"app"},'My first react!');
單看一行可能沒什麼感受,但專案龐大的話,會變得很可怕
JSX的用法要注意幾個地方
- 屬性的寫法 時常注意 Dev Tool 的 console 提醒!
// 屬性 class 要寫成 className , 因為會跟 JS 的 class建構類別衝突
// 屬性 for 要寫htmlFor 否則跟JS迴圈衝突
<label className="name" htmlFor="name">
- 所有元素都要關閉
<a href="#"> 前往首頁 </a>
<img src="images/test.jpg" width="100" height="100" alt="..." />
- 事件要用 camel case
<div onClick={() => console.log('click')}>
button
</div>
- style 屬性也要用 JS 寫法,且 camel case、'' 單引號包值、最外圍 ,分開各屬性
<div style={{width:'100px', fontSize:'16px', backgroundColor:'red'}}></div>
{{border:'1px solid red'}}
// 第一層{}表示我們想用 JS 的變數代替JSX
// 第二層 {} 表示這是一個JS物件
//有 dash - 的屬性 要把 dash 拿掉並用駝峰寫法
- 寫JS要用 包起來
// JSX裡要帶JS的話,用{}
const btnText = () => {
return "just click"
}
const APP = () =>{
// const btnText = "click it!"; 單純str這個也可以
return (
<div>
<label class="name" for="name">
Enter Name:
</label>
<input id="name" type="text" />
<button>{btnText()}</button> //這裡用{}引用JS變數或者函式 要注意這不是JS物件!
</div>
);
}
- 不可直接帶 類型的 JS 物件進 JSX,是 invalid 的
const APP = () =>{
const btnText = {text:"click it!"};
return (
<div>
<label class="name" for="name">
Enter Name:
</label>
<input id="name" type="text" />
<button>{btnText}</button>
</div>
);
}
Error: Objects are not valid as a React child
(found: object with keys {text}).
If you meant to render a collection of children, use an array instead.
// 必須寫成
<button>{btnText.text}</button>
- return 要一個頂端 tag 包住所有內容,就想是一個完整的組件容器裝載著組件
// 只有一行code 直接接return後面不換行
return <div>Hi!there</div>
// 多行code 用()包住
return (
<div className="App">
My first react!
</div>
);
// 這樣是不行的
return (
<span> Look~ </ span>
<div className="App">
My first react!
</div>
);
// 使用 Fragment
return (
<>
<span> Look~ </ span>
<div className="App">
My first react!
</div>
</>
);
生命週期
https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
*大概的組件生命週期路線
最初在理解生命週期時,算是蠻苦惱的。原本直接學習 Functional Component (Hook),後來卻是回頭理解 Class Component 的生命週期流程才比較能體會。

constructor 建立組件 (但目前很少用了,被箭頭函式取代) -> render 渲染 -> componentDidMount 渲染完成 -> render(re-render by updating) 若有更新再次渲染 -> componentDidUpdate 更新渲染完成 -> componentWillUnmount 刪除組件前 -> 組件已消失
*什麼是刪除之前?應該說什麼是刪除?
就是當 React 發現到 VirtualDOM 與 RealDOM 之間有不同時,而需要移除 RealDOM 裡,VD 沒有的部分,就是會將之刪除!那麼刪除前就會執行Unmount 的代碼。要注意 componentWillUnmount 裡 setState 是沒有卵用的,因為不會觸發 render