{%hackmd lTq14m8-RK6cksBvQ0Rnrg %} # React React是一個自由及開放原始碼的前端JavaScript工具庫, 用於基於UI組件構建使用者介面。 它由Meta和由個人開發者和公司組成的社群維護。 ## Components Components可區分為兩大類型:Function Components vs Class Components ### Function Components ### Class Components ## Virtual DOM ### 什麼是Virtual DOM React為了解決MVC、MVP、MVVM等架構的問題。以「當 Model 發生改變時直接重新渲染 View」的方式,引入 Virtual DOM 的概念。透過 JavaScript 物件來描述 DOM 結構,產生當下 Model 對應的 Virtual DOM 結構,再和上次的 Virtual DOM 結構透過 Diff 演算法比較,再將兩者差異建立在真實 DOM 上。  參考資料: [Virtual-DOM-的起源](https://hackmd.io/@Heidi-Liu/virtual-dom#%E8%A3%9C%E5%85%85%EF%BC%9AVirtual-DOM-%E7%9A%84%E8%B5%B7%E6%BA%90) ### Virtual DOM的流程 1. 初次使用setState()方法的時候,React會先複製一份dom的物件(即為Virtual DOM 2. 當React component的state改變時,會比對先前的Virtual DOM和當前的 Virtual DOM差異,稱之為**diff運算** 3. Virtual DOM先用自己的演算法(diff)算出實際需要更新的部分,比對兩者差異之後,再去更動真實的DOM,有效減少渲染的次數 ,提高效能 這是一般的html結構 ```htmlembedded <div id="header"> <h1 class="title">Apple</h1> <p class="content">lemon</p> </div> ``` 這是Virtual DOM的結構,是JavaScript模擬出來的物件, 會以以下的格式儲存起來 ```json { tag: "div", props: { id: "header" }, children: [ { tag: "h1", props: { className: "title" }, children: ["Apple"] }, { tag: "p", props: { className: "content" }, children: ["lemon"] } ] } ``` * type: DOM標籤名稱 * props:DOM屬性 * children:DOM子元素 下方就用程式碼來稍微模擬一下Virtual DOM的執行過程 1. createELement :先使用Virtual DOM提供的createELement方法來生成真實的DOM ```javascript var count = 0; var tree = render(count); var rootNode = createElement(tree); document.body.appendChild(rootNode); ``` 2. 當count變動時 Virtual DOM進行比對 再將差異patch到實際的DOM ```javascript count++ var newTree = render(count); var patches = diff(tree, newTree); rootNode = patch(rootNode, patches); tree = newTree; ``` **ReactElement** ```javascript const element = <h1 id="hello">Hello, world</h1> ``` 上面的代碼經過編譯後其實生成的代碼是這樣的: ```javascript React.createElement("h1", { id: "hello" }, "Hello, world"); ``` 執行 React.createElement 函數,會返回類似於下面的一個 js 對象,這個對象就是我們所說的 React 元素: ```javascript const element = { type: 'h1', props: { id: 'hello', children: 'hello world' } } ``` React 元素也可以是用戶自定義的組件: ```javascript function Button(props) { return <button style={{ color }}>{props.children}</button>; } const buttonComp = <Button color="red">點擊我</Button> ``` #### 什麼是patch?patch指的是在原有的DOM結構上做異動 **關於diff演算法** Virtual DOM的diff演算法為O(n) 與傳統的差異在於下幾點: 1. Virtual DOM只會比較同一層級的節點 2. 同一層的節點為了識別個別具有唯一的key,為了避免節點只是移動又被重新創建一次 3. 如果發現節點不見了其子節點也會一併刪除,不會做進一步的比對 以往如果是手動操作,每操作一次就會更新一次DOM,如果是透過react setState就會是將多個操作合併為一次的操作,避免頻繁更新頁面,因此開發者只要專注在資料邏輯上,畫面的更新機制全部交給React處理即可。  參考資料: [理解React Virtual DOM](https://medium.com/coding-hot-pot/react-vitural-dom-134fa79e0d4f) [你不知道的 React Virtual DOM](https://www.readfog.com/a/1641376221189214208) ## 傳值 @StanShih React屬於單向資料流,所有的資料都是從父層往子層傳遞 React的畫面是由許多元件組合建構而成,因此元件算是React的核心靈魂  ### 父傳子 Props ```javascript= import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; class App extends Component { render() { return ( <div className="App"> <h1>Hello World! React</h1> <Person name="Andy" age="21"/> <Person name="Jack" age="22"/> </div> ); } } export default App; ``` ```javascript= import React from 'react'; const person =(props)=>{ return <p> I'm {props.name} and I'am {props.age} yesrs old.</p> } export default person; ``` ### 子傳父 #### callback #### ## JSX JSX 是 JavaScript 的語法擴展,它允許你以類似 HTML 的語法來描述你的 UI。JSX 的好處在於除了需遵守三個 JSX 規則之外,你無需學習 HTML 和 JavaScript 之外的任何新符號或語法。 JSX 是一種似 HTML 結構並混合 JavaScript 語法功能的語法糖(Syntatic Sugar),背後其實封裝了 React Raw API,但相較於 React Raw API,更加簡潔與直觀,並帶有明顯的 UI 結構,因此更好閱讀與理解。一眼就能理解為什麼寫 React 時,通常都是直接用 JSX 語法,而非使用 createElement。不過,依然必須要清楚 JSX 僅是一種 React 提供的語法糖 ,並且「不能」被瀏覽器直接理解。。 JSX 規則 > 1. 返回單一根元素 > 若要從元件傳回多個元素,請使用單一父標籤包裝它們。 > 2. 關閉所有標籤 > JSX 要求標籤明確關閉:自關閉標籤(如`<img>`必須成為`<img />`)和包裝標籤(如 > `<li>oranges`必須寫為`<li>oranges</li>`。 > 3. 大多數東西都採用駝峰命名法! > JSX 變成 JavaScript,用 JSX 寫的屬性成為 JavaScript 物件的鍵。在您自己的元件中,您經常希望將這些屬性讀入變數中。但 JavaScript 對變數名稱有限制。例如,它們的名稱不能包含破折號或保留字,例如class. > > 這就是為什麼在 React 中,許多 HTML 和 SVG 屬性都是用駝峰命名法編寫的。例如,stroke-width您可以使用strokeWidth. 因為class是一個保留字,在 React 中你可以這樣寫,以對應的 DOM 屬性className命名: 需注意的是,瀏覽器無法直接理解 JSX,因此你需要一個 JavaScript 編譯器,例如 Babel,將你的 JSX 語法轉換為常規 JavaScript。 同樣地將一樣的 Hello World !     ## 生命週期(Lifecycle) **1. Mounting(掛載):** * constructor(): 在組件被創建時調用,用於初始化狀態。 * static getDerivedStateFromProps(): 在組件被創建和每次接收新的props時都會調用,用於更新狀態。 * render(): 根據組件的狀態和屬性生成虛擬DOM。 * componentDidMount(): 在組件被插入DOM後調用,通常用於執行一次性的資源請求或設定訂閱。 **2. Updating(更新):** * static getDerivedStateFromProps(): 同樣在更新階段調用。 * shouldComponentUpdate(): 在更新前調用,返回false可以阻止組件的重新渲染。 * render(): 更新虛擬DOM。 * getSnapshotBeforeUpdate(): 在實際DOM更新之前獲取一些信息,通常用於捕獲滾動位置等。 * componentDidUpdate(): 在組件完成更新後調用,通常用於執行一些額外的操作,比如狀態的同步。 **3. Unmounting(卸載):** * componentWillUnmount(): 在組件即將從DOM中卸載時調用,通常用於清理計時器、取消綁定等資源回收操作。 ### useEffect React Hooks 中的一個關鍵函數,用於處理副作用(side effects)的邏輯。副作用通常包括資料的獲取、訂閱事件、手動操作DOM等,而這些操作可能會影響組件的狀態和渲染。 ## Hook? 在 React 16.8 之前,如果我們想要使用到生命週期的方法或狀態 (state),那我們只能使用 React 的 class component。但 React hooks 的出現,讓我們即使使用 functional component,也能夠使用到 React 的功能和狀態。在 React 中,用 `use` 開頭的函式我們會把它稱之為 Hook,有些 Hooks 是 React 內建的功能,例如:`useEffect`,但我們也可以創造自己的 Hooks。Hooks 相較於函式更嚴謹、有一些需要遵守的規範,我們接下來在下方會提到。 ### Hook 解決了什麼問題? React 團隊開發 Hooks 主要為了解決這三個原因 #### 狀態相關的邏輯 (stateful logics) 在 class component 之間難以複用 在使用 class component 時,React 並沒有提供可以將重複的邏輯添加到元件的方法。因此,開發者可能使用 `render props` 或是 `higher-order components` 的方式達到,但這個缺點會是需要重新架構元件,不僅麻煩、而且程式碼也不易讀 (React 文件戲稱為 wrapper hell)。因此, Hook 的解決的主要問題之一,正是讓共享狀態邏輯。 使用 Hooks,開發者可以從元件中提取狀態相關的邏輯,並對它進行獨立複用。我們也不需要重組元件,就可以在元件中複用相同邏輯。舉例來說,如果某個應用程式需要偵測頁面滑動,並根據滑動來觸發某些函式,這時我們可以寫一個 `useScroll`,並在不同頁面共享這個 `useScroll` 的狀態邏輯。目前在 React 的社群中,有很多 Hooks 的函式庫,便提供了各式各樣可重複使用的 Hooks。 #### 在 Hooks 出現前,複雜元件的邏輯會越寫越讓人難理解 當 class component 越來越龐大或邏輯複雜時,我們可能會在同一個生命週期方法內需要加入很多不相關的邏輯,例如:`componentDidMount` 要處理 data fetching 和事件偵聽器邏輯,不僅難以理解也不好維護,且在很多情況下,也無法把這些元件拆成更小的元件。 為了解決此問題, Hooks 允許將一個元件拆為更小的函式,而不是根據生命週期的方法拆分,例如上段例子,data fetching 和 事件偵聽器兩種邏輯,可以在同一個元件,通過兩個 `useEffect` 各自處理,又或者兩者拆成兩個 custom hooks。透過這樣細分,不相關的邏輯可以拆到不同的 `useEffect`,讓副作用的邏輯更好管理。 #### class 對於開發者來說不好理解 React 團隊發現,class 可能會是學習 React 的主要障礙。因為 class 的概念在 JavaScript 和其他語言中相當不同 (在 JavaScript 當中,class 是語法糖),如果開發者過去是寫其他語言,轉來寫 JavaScript 時,需要特別了解 class 在 JavaScript 是如何運作的。 為了解決這些問題,Hooks 可以在沒有 class 的情況下使用更多 React 的特性。從概念上講,React 元件一直更接近函式。 Hooks 包含函式,但不犧牲 React 的實用精神,且不需要特別學習複雜的 functional or reactive programming。 ## Functional Components vs Class Components: 
×
Sign in
Email
Password
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