本篇筆記摘錄自官方文件 Your First Component
Component (元件) 是 React 的核心觀念之一,是建構 UI 的基礎。
Components: UI building blocks
- React 使用 component 來結合標記式語言( markup )、CSS、JavaScript。
- 是可以重複使用的 UI 元素,可以渲染在每一個頁面,當專案變大時,這些可以重複使用的元件將加速我們的開發。
- 在 React 裡,所有 UI 的部分都是 component。
- 就像 HTML tags 一樣,可以使用巢狀結構來設計整個頁面。
<PageLayout>
<NavigationHeader>
<SearchBar />
<Link to="/docs">Docs</Link>
</NavigationHeader>
<Sidebar />
<PageContent>
<TableOfContents />
<DocumentationText />
</PageContent>
</PageLayout>
- React 的開源社群有許多 component 可以使用。
(像是 Chakra UI & MaterialUI.)
Defining a component
Component 是一個 JavaScript 的函式,我們可以在裡面使用標記式語言 (markup )。
Component 與一般 JavaScript function 的差異:
- 命名字首必須為大寫
- return JSX markup
< 建立 Component 的三個步驟 >
- Step 1 : Export the component
default export
可以標記出檔案中主要的函式,使內容之後可以透過 import 匯入其他檔案。
(export default
這個前綴詞為 JavaScript 語法,並非 React 新創) - Step 2 : Define the function
React component 是 JavaScript 的函式,但是字首必須為大寫,否則將無法運作。
例如:function Profile() { }
- Step 3 : Add markup
下方程式碼雖然看起來與 HTML 非常相似,但它實際上是一種 JavaScript 的擴充語法,這種語法稱為 JSX,JSX 讓我們可以在 JavaScript 中嵌入標記語言。
return 的內容可以只有一行,就像下方的範例一樣。
return <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />;
必須注意的是:如果回傳的內容不止一行,必須使用括號包覆,並且給它們一個共享的父標籤 ( parent tag ),像是 <div>…</div> 或是 <>…</>。
如果沒有使用括號包覆,與 return 位於不同行的程式碼將被忽略。
return (
<div>
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
</div>
);
Using a component
在下面的範例中,我們首先定義了Profile
元件,接著,我們可以在其他 component 中巢狀使用它。
舉例來說,我們可以輸出一個Gallery
元件,並在這個Gallery
元件中放入多個Profile
元件。
( 將左側拉桿向右移動,可以看見程式碼的部分,拉開後點擊左上角三條線漢堡圖示可以看見完整檔案,右邊則為輸出結果。 )
瀏覽器看到的是什麼呢?
上方範例中,<section>
為小寫開頭,<Profile>
為大寫開頭,因此 React 可以藉此分辨出誰是 HTML tag、誰是 Component。
而Profile
中包含了<img>
,因此瀏覽器看到的內容會是這樣的:
<section>
<h1>Amazing scientists</h1>
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
</section>
Nesting and organizing components
Component 是 JavaScript 函式,所以我們可以將多個元件放在同一個檔案中,當元件相對較小或彼此之間關係緊密時是非常方便的。
如果檔案變得擁擠,我們也可以把元件提取出來到另一個檔案中。
以剛剛上方的例子來說,我們也可以把Profile
提取出來,讓它自己獨立在一個檔案中。
Profile
元件在Gallery
元件中渲染多次,因此我們可以說Gallery
是一個父元件 ( parent component ),渲染著它的每個 ”child”,也就是Profile
。
這也是 React 很棒的地方之一,你只需要定義元件一次,在這之後,你可以在任何你想使用的地方使用它,並且不限次數。
注意:
元件雖然可以在其他元件中渲染,但不要在巢狀結構內定義它們!!!
這會使運作緩慢且發生 bug,每一個元件都應該被定義在最頂層。
錯誤範例:
export default function Gallery() {
// 🔴 Never define a component inside another component!
function Profile() {
// ...
}
// ...
}
正確範例:
export default function Gallery() {
// ...
}
// ✅ Declare components at the top level
function Profile() {
// ...
}
當子元件需要父元件的資料時,可以使用 props 傳遞,而非巢狀定義它們。