你的第一個元件

元件是 React 的核心概念之一。它們是你構建使用者介面 (UI) 的基礎,這使得它們成為開始你的 React 旅程的絕佳起點!

你將學到

  • 什麼是元件
  • 元件在 React 應用程式中扮演什麼角色
  • 如何編寫你的第一個 React 元件

元件:UI 構建塊

在網頁上,HTML 允許我們使用其內建的標籤集(例如 <h1><li>)來建立豐富的結構化文件。

<article>
<h1>My First Component</h1>
<ol>
<li>Components: UI Building Blocks</li>
<li>Defining a Component</li>
<li>Using a Component</li>
</ol>
</article>

這個標記代表這篇文章 <article>、其標題 <h1>,以及一個(簡略的)目錄作為有序列表 <ol>。像這樣的標記,結合用於樣式的 CSS 和用於互動性的 JavaScript,構成了你看到的每個側邊欄、頭像、模態框、下拉選單——網頁上的每個 UI 片段。

React 允許你將標記、CSS 和 JavaScript 組合到自定義的「元件」中,為你的應用程式提供可重複使用的 UI 元素。 你在上面看到的目錄程式碼可以轉換成一個 <TableOfContents /> 元件,你可以在每個頁面上渲染它。在底層,它仍然使用相同的 HTML 標籤,例如 <article><h1> 等等。

就像 HTML 標籤一樣,你可以組合、排序和嵌套元件來設計整個頁面。例如,你正在閱讀的文檔頁面是由 React 元件組成的。

<PageLayout>
<NavigationHeader>
<SearchBar />
<Link to="/docs">Docs</Link>
</NavigationHeader>
<Sidebar />
<PageContent>
<TableOfContents />
<DocumentationText />
</PageContent>
</PageLayout>

隨著你的專案增長,你會注意到你的許多設計可以通過重複使用你已經編寫的元件來組成,從而加快你的開發速度。我們上面的目錄可以通過 <TableOfContents /> 新增到任何螢幕!你甚至可以使用 React 開源社群共享的數千個元件(例如 Chakra UIMaterial UI)來快速啟動你的專案。

定義元件

傳統上,在建立網頁時,網頁開發人員會先標記他們的內容,然後通過添加一些 JavaScript 來增加互動性。當互動性在網路上還只是錦上添花時,這種方法效果很好。現在,許多網站和所有應用程式都期望有互動性。React 將互動性放在首位,同時仍然使用相同的技術:React 元件是一個 JavaScript 函式,你可以在其中添加標記 以下是它的樣子(你可以編輯下面的範例)

export default function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3Am.jpg"
      alt="Katherine Johnson"
    />
  )
}

以下是構建元件的方法

步驟 1:匯出元件

前綴詞 export default標準的 JavaScript 語法(並非 React 特有的)。它允許您標記檔案中的主要函式,以便之後可以從其他檔案匯入它。(更多關於匯入的內容,請參閱匯入和匯出元件!)

步驟 2:定義函式

使用 function Profile() { },您可以定義一個名為 Profile 的 JavaScript 函式。

陷阱

React 元件是普通的 JavaScript 函式,但它們的名稱必須以大寫字母開頭,否則它們將無法運作!

步驟 3:新增標記

該元件會傳回一個帶有 srcalt 屬性的 <img /> 標籤。<img /> 看起來像 HTML,但實際上它底層是 JavaScript!這種語法稱為 JSX,它允許您在 JavaScript 中嵌入標記。

Return 陳述式可以寫在同一行,就像此元件一樣

return <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />;

但如果您的標記與 return 關鍵字不在同一行,則必須將其用一對括號括起來

return (
<div>
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
</div>
);

陷阱

沒有括號,return 之後行上的任何程式碼都將被忽略

使用元件

現在您已經定義了 Profile 元件,您可以將它巢狀在其他元件中。例如,您可以匯出一個使用多個 Profile 元件的 Gallery 元件

function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3As.jpg"
      alt="Katherine Johnson"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

瀏覽器看到的內容

注意大小寫的區別

  • <section> 是小寫的,因此 React 知道我們指的是 HTML 標籤。
  • <Profile /> 以大寫字母 P 開頭,因此 React 知道我們要使用名為 Profile 的元件。

Profile 包含更多 HTML:<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>

巢狀和組織元件

元件是普通的 JavaScript 函式,因此您可以將多個元件放在同一個檔案中。當元件相對較小或彼此緊密關聯時,這很方便。如果這個檔案變得擁擠,您可以隨時將 Profile 移到單獨的檔案中。您很快就會在關於匯入的頁面上學習如何操作。

因為 Profile 元件是在 Gallery 內部渲染的——即使是多次!——我們可以說 Gallery 是一個父元件,它將每個 Profile 渲染為「子元件」。這是 React 的神奇之處:您可以定義一次元件,然後在任意多個地方和任意多次使用它。

陷阱

元件可以渲染其他元件,但您絕不能巢狀它們的定義:

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() {
// ...
}

當子元件需要來自父元件的一些資料時,請透過屬性傳遞它,而不是巢狀定義。

深入探討

一路向下的元件

您的 React 應用程式始於一個「根」組件。通常,當您開始一個新專案時,它會自動建立。例如,如果您使用 CodeSandbox 或如果您使用框架 Next.js,根組件會在 pages/index.js 中定義。在這些範例中,您一直在匯出根組件。

大多數 React 應用程式都會一路使用組件。這表示您不僅會將組件用於按鈕等可重複使用的片段,還會將其用於較大的片段,例如側邊欄、列表,最終甚至是完整的頁面!組件是組織 UI 程式碼和標記的便捷方式,即使其中一些組件只使用一次。

基於 React 的框架 更進一步。它們不是使用空的 HTML 檔案並讓 React 用 JavaScript「接管」管理頁面,而是 *也* 從您的 React 組件自動產生 HTML。這允許您的應用程式在 JavaScript 程式碼載入之前顯示一些內容。

儘管如此,許多網站只使用 React 來 為現有的 HTML 頁面添加互動性。 它們有許多根組件,而不是整個頁面只有一個。您可以根據需要使用多個或少量 React。

重點回顧...

您剛剛初次體驗了 React!讓我們回顧一些重點。

  • React 讓您可以建立組件,應用程式的可重複使用 UI 元素。

  • 在 React 應用程式中,每個 UI 片段都是一個組件。

  • React 組件是普通的 JavaScript 函式,除了

    1. 它們的名稱始終以大寫字母開頭。
    2. 它們會返回 JSX 標記。

挑戰 1 4:
匯出組件 ...

這個沙盒無法運作,因為根組件未匯出

function Profile() {
  return (
    <img
      src="https://i.imgur.com/lICfvbD.jpg"
      alt="Aklilu Lemma"
    />
  );
}

在查看解決方案之前,請嘗試自行修復!