畫面組裝的藍圖:component 初探
什麼是 Component
Component(元件) 是 React 的核心概念之一,它是構成使用者介面(UI)的獨立、可重複使用的程式碼區塊。你可以把 Component 想像成一個個小積木,每個 Component 負責畫面的一部分(例如按鈕、表單、導覽列等),這些小積木可以組合起來形成完整的網頁。
在 React 中,Component 可以是:
-
函數式元件(Function Component):使用 JavaScript 函數定義,現在是 React 的主流方式。
-
類元件(Class Component):使用 ES6 的 Class 語法,較舊的方式,現在較少使用。
範例: 假設你要製作一個顯示「Hello, World!」的元件:
// 函數式元件
function Greeting() {
return <h1>Hello, World!</h1>;
}
這個 Greeting 元件是一個簡單的函數,返回 JSX(一種看起來像 HTML 的語法,用來描述 UI)。React 會將這個元件渲染到畫面上。
定義 Component
在 React 中,定義 Component 的方式主要使用 函數式元件。以下是定義元件的步驟:
-
建立一個函數:函數名稱通常以大寫字母開頭。
-
返回 JSX:函數必須返回 JSX,用來描述元件的畫面結構。
-
可選:使用 Props:元件可以接受外部傳入的參數(Props),讓元件更靈活。
完整範例: 假設你要定義一個顯示使用者名稱的元件:
// 定義一個函數式元件
function UserProfile() {
return (
<div>
<h2>使用者資料</h2>
<p>姓名:小明</p>
</div>
);
}
步驟解析:
-
函數名稱 UserProfile 是大寫開頭。
-
返回的 JSX 包含一個
<div>
,裡面有標題和段落。 -
這個元件目前是靜態的,之後會學到如何用 Props 動態傳入資料。
呼叫 Component
定義好 Component 後,你需要在其他地方「呼叫」它來使用。React 的 Component 可以像 HTML 標籤一樣被使用,只不過是用你定義的元件名稱。
範例: 假設你已經定義了 UserProfile 元件,現在要在主應用程式中呼叫它:
import React from "react";
import ReactDOM from "react-dom/client";
// 定義元件
function UserProfile() {
return (
<div>
<h2>使用者資料</h2>
<p>姓名:小明</p>
</div>
);
}
// 主應用程式
function App() {
return (
<div>
<h1>我的網站</h1>
<UserProfile /> {/* 呼叫元件 */}
</div>
);
}
// 渲染到畫面
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
步驟解析:
-
在 App 元件中,使用
<UserProfile />
來呼叫 UserProfile 元件,就像使用 HTML 標籤一樣。 -
最終,React 會將 UserProfile 的內容渲染到畫面,顯示「使用者資料」和「姓名:小明」。
Import 與 Export Component
在實際專案中,元件通常會寫在不同的檔案中,這樣程式碼更模組化。你需要使用 ES6 的模組系統 來匯入(Import)和匯出(Export)元件。
範例: 假設你有兩個檔案:UserProfile.js 和 App.js。
-
UserProfile.js(定義並匯出元件):
// UserProfile.js
function UserProfile() {
return (
<div>
<h2>使用者資料</h2>
<p>姓名:小明</p>
</div>
);
}
export default UserProfile; // 匯出元件 -
App.js(匯入並使用元件):
// App.js
import React from "react";
import UserProfile from "./UserProfile"; // 匯入元件
function App() {
return (
<div>
<h1>我的網站</h1>
<UserProfile /> {/* 使用匯入的元件 */}
</div>
);
}
export default App; -
主程式(index.js):
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
步驟解析:
-
在 UserProfile.js 中,使用 export default 匯出元件。
-
在 App.js 中,使用 import 匯入 UserProfile 元件,然後像標籤一樣使用。
-
檔案結構保持清晰,方便維護和重複使用。
Props
Props(Properties)是用來傳遞資料給元件的機制,讓元件可以動態顯示不同的內容。Props 就像函數的參數,父元件可以傳遞資料給子元件。
範例: 改進之前的 UserProfile 元件,讓它可以接受動態的姓名:
-
UserProfile.js(接受 Props):
// UserProfile.js
function UserProfile(props) {
return (
<div>
<h2>使用者資料</h2>
<p>姓名:{props.name}</p>
</div>
);
}
export default UserProfile; -
App.js(傳遞 Props):
// App.js
import React from "react";
import UserProfile from "./UserProfile";
function App() {
return (
<div>
<h1>我的網站</h1>
<UserProfile name="小明" /> {/* 傳遞 name 屬性 */}
<UserProfile name="小華" /> {/* 傳遞不同的 name */}
</div>
);
}
export default App;
步驟解析:
-
在 UserProfile 元件中,props 是一個物件,包含父元件傳來的屬性(例如 name)。
-
在 App 中,使用
<UserProfile name="小明" />
傳遞 name 屬性。 -
畫面會顯示兩個 UserProfile 元件,分別顯示「姓名:小明」和「姓名:小華」。
父 Component 與子 Component
在 React 中,元件之間有層次關係:
-
父元件:呼叫其他元件的元件(例如 App)。
-
子元件:被父元件呼叫的元件(例如 UserProfile)。
父元件可以透過 Props 傳遞資料給子元件,子元件則負責渲染這些資料。
範例: 延續上面的程式碼,App 是父元件,UserProfile 是子元件。父元件可以傳遞多個 Props 給子元件:
// UserProfile.js
function UserProfile(props) {
return (
<div>
<h2>使用者資料</h2>
<p>姓名:{props.name}</p>
<p>年齡:{props.age}</p>
</div>
);
}
export default UserProfile;
// App.js
import React from "react";
import UserProfile from "./UserProfile";
function App() {
return (
<div>
<h1>我的網站</h1>
<UserProfile name="小明" age={25} />
<UserProfile name="小華" age={30} />
</div>
);
}
export default App;
步驟解析:
-
App 是父元件,透過 Props 傳遞 name 和 age 給子元件 UserProfile。
-
UserProfile 是子元件,接收 Props 並渲染到畫面。
-
這種結構讓程式碼更有組織性,且子元件可以重複使用。
Component 的 Render 與 Re-render
在 React 中,Render 是指元件根據當前的 Props 和 State(狀態)生成 JSX,並由 React 轉換為真實的 DOM 顯示在畫面上。Re-render 則是當 Props 或 State 改變時,React 會重新執行元件的渲染。
範例: 假設你有一個計數器元件,當按鈕被點擊時,計數器會增加,並觸發 Re-render:
// Counter.js
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0); // 使用 State 來儲存計數
return (
<div>
<p>你點擊了 {count} 次</p>
<button onClick={() => setCount(count + 1)}>點擊我</button>
</div>
);
}
export default Counter;
// App.js
import React from "react";
import Counter from "./Counter";
function App() {
return (
<div>
<h1>我的網站</h1>
<Counter />
</div>
);
}
export default App;
步驟解析:
-
useState 是 React 的 Hook,用來管理元件的狀態(這裡是 count)。
-
當你點擊按鈕,setCount 會更新 count,觸發元件重新渲染(Re-render)。
-
React 會比較新舊 DOM,只更新改變的部分(例如計數的數字),這是 React 的高效之處。
為什麼 Component 命名中的首字母必須為大寫
在 React 中,元件名稱的首字母必須大寫,這是因為 React 會根據名稱的首字母來區分 React 元件 和 HTML 標籤:
-
小寫名稱:React 認為是原生的 HTML 標籤(例如
<div>
、<p>
)。 -
大寫名稱:React 認為是自訂的元件(例如
<UserProfile>
)。
範例: 假設你定義了一個元件,但使用小寫名稱:
// 錯誤範例
function userProfile() {
return <div>錯誤的元件名稱</div>;
}
// 正確範例
function UserProfile() {
return <div>正確的元件名稱</div>;
}
為什麼必須大寫:
-
React 使用 JSX 語法,JSX 會將標籤轉換為 JavaScript 程式碼。如果元件名稱是小寫,React 會誤以為它是一個 HTML 標籤,導致無法正確渲染。
-
大寫名稱讓 React 知道這是一個自訂的元件,會調用對應的函數來渲染。
實務建議:
-
總是用大寫字母開頭命名元件(例如 UserProfile、MyButton)。
-
檔案名稱通常與元件名稱一致(例如 UserProfile.js)。
總結
透過以上教學,你應該對 React 的 Component 有初步了解:
-
什麼是 Component:它是 UI 的積木,可重複使用。
-
定義 Component:使用函數返回 JSX。
-
呼叫 Component:像 HTML 標籤一樣使用元件。
-
Import 與 Export:用模組系統組織程式碼。
-
Props:讓元件動態顯示資料。
-
父與子 Component:透過 Props 傳遞資料,形成層次結構。
-
Render 與 Re-render:React 根據 Props 和 State 渲染畫面,狀態改變時重新渲染。
-
為什麼首字母大寫:React 用來區分元件和 HTML 標籤。
操作建議:
-
建立一個 React 專案(可以使用 create-react-app 或 Vite)。
-
將上述範例程式碼複製到你的專案中,嘗試運行並修改 Props 或 State。
-
觀察畫面變化,熟悉元件的渲染行為。