使用 JSX 撰寫標記

JSX 是一種 JavaScript 的語法擴充,可讓你像撰寫 HTML 標記一樣在 JavaScript 檔案中編寫。雖然還有其他方法可以撰寫元件,但大多數 React 開發人員更喜歡 JSX 的簡潔性,而且大多數程式碼庫都使用它。

你將學到

  • 為什麼 React 將標記與渲染邏輯混合在一起
  • JSX 與 HTML 的不同之處
  • 如何使用 JSX 顯示資訊

JSX:將標記放入 JavaScript 中

Web 一直建立在 HTML、CSS 和 JavaScript 的基礎上。多年來,網頁開發人員將內容保存在 HTML 中,設計保存在 CSS 中,邏輯保存在 JavaScript 中,通常是在不同的檔案中!內容在 HTML 內部被標記,而頁面的邏輯則單獨存在於 JavaScript 中。

HTML markup with purple background and a div with two child tags: p and form.
HTML markup with purple background and a div with two child tags: p and form.

HTML

Three JavaScript handlers with yellow background: onSubmit, onLogin, and onClick.
Three JavaScript handlers with yellow background: onSubmit, onLogin, and onClick.

JavaScript

但隨著 Web 變得更具互動性,邏輯越來越決定內容。JavaScript 負責 HTML!這就是為什麼在 React 中,渲染邏輯和標記位於元件中的同一個地方。

React component with HTML and JavaScript from previous examples mixed. Function name is Sidebar which calls the function isLoggedIn, highlighted in yellow. Nested inside the function highlighted in purple is the p tag from before, and a Form tag referencing the component shown in the next diagram.
React component with HTML and JavaScript from previous examples mixed. Function name is Sidebar which calls the function isLoggedIn, highlighted in yellow. Nested inside the function highlighted in purple is the p tag from before, and a Form tag referencing the component shown in the next diagram.

Sidebar.js React 元件

React component with HTML and JavaScript from previous examples mixed. Function name is Form containing two handlers onClick and onSubmit highlighted in yellow. Following the handlers is HTML highlighted in purple. The HTML contains a form element with a nested input element, each with an onClick prop.
React component with HTML and JavaScript from previous examples mixed. Function name is Form containing two handlers onClick and onSubmit highlighted in yellow. Following the handlers is HTML highlighted in purple. The HTML contains a form element with a nested input element, each with an onClick prop.

Form.js React 元件

將按鈕的渲染邏輯和標記放在一起可以確保它們在每次編輯時都保持同步。相反,不相關的細節(例如按鈕的標記和側邊欄的標記)彼此隔離,因此可以更安全地單獨更改其中任何一個。

每個 React 元件都是一個 JavaScript 函式,其中可能包含一些 React 渲染到瀏覽器中的標記。React 元件使用一種稱為 JSX 的語法擴充來表示該標記。JSX 看起來很像 HTML,但它更嚴格一些,並且可以顯示動態資訊。理解這一點的最佳方法是將一些 HTML 標記轉換為 JSX 標記。

備註

JSX 和 React 是兩個不同的東西。它們經常一起使用,但你可以獨立使用它們。JSX 是一種語法擴充,而 React 是一個 JavaScript 函式庫。

將 HTML 轉換為 JSX

假設你有一些(完全有效的)HTML

<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
<li>Invent new traffic lights
<li>Rehearse a movie scene
<li>Improve the spectrum technology
</ul>

而你想把它放到你的元件中

export default function TodoList() {
return (
// ???
)
}

如果你直接複製貼上它,它將無法正常工作

export default function TodoList() {
  return (
    // This doesn't quite work!
    <h1>Hedy Lamarr's Todos</h1>
    <img 
      src="https://i.imgur.com/yXOvdOSs.jpg" 
      alt="Hedy Lamarr" 
      class="photo"
    >
    <ul>
      <li>Invent new traffic lights
      <li>Rehearse a movie scene
      <li>Improve the spectrum technology
    </ul>

這是因為 JSX 更嚴格,並且比 HTML 有更多規則!如果你閱讀上面的錯誤訊息,它們將引導你修復標記,或者你可以按照下面的指南進行操作。

備註

大多數情況下,React 的螢幕錯誤訊息將幫助你找到問題所在。如果你遇到困難,請閱讀它們!

JSX 的規則

1. 傳回單一根元素

要從元件傳回多個元素,請使用單個父標籤將它們包裝起來。

例如,你可以使用 <div>

<div>
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
...
</ul>
</div>

如果你不想在標記中新增額外的 <div>,你可以改寫 <></>

<>
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
...
</ul>
</>

這個空標籤稱為Fragment。 Fragments 可讓你將事物分組,而不會在瀏覽器 HTML 樹狀結構中留下任何痕跡。

深入探討

為什麼多個 JSX 標籤需要被包裹?

JSX 看起來像 HTML,但在底層它會被轉換成普通的 JavaScript 物件。如果沒有將兩個物件包裹在一個陣列中,則無法從函式返回它們。這解釋了為什麼在沒有將兩個 JSX 標籤包裹在另一個標籤或 Fragment 中的情況下,也無法返回它們。

2. 關閉所有標籤

JSX 要求明確關閉標籤:像 <img> 這樣的自閉合標籤必須變成 <img />,而像 <li>oranges 這樣的包裝標籤必須寫成 <li>oranges</li>

這就是海蒂·拉瑪的圖片和清單項目如何被關閉的

<>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
/>
<ul>
<li>Invent new traffic lights</li>
<li>Rehearse a movie scene</li>
<li>Improve the spectrum technology</li>
</ul>
</>

3. 將所有大多數東西都改成 camelCase!

JSX 會轉換成 JavaScript,並且在 JSX 中編寫的屬性會成為 JavaScript 物件的鍵。在您自己的組件中,您通常會希望將這些屬性讀取到變數中。但是 JavaScript 對變數名稱有限制。例如,它們的名稱不能包含破折號或像 class 這樣的保留字。

這就是為什麼在 React 中,許多 HTML 和 SVG 屬性都使用 camelCase 編寫。例如,您使用 strokeWidth 代替 stroke-width。由於 class 是一個保留字,因此在 React 中,您改寫 className,以相對應的 DOM 屬性命名。

<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
className="photo"
/>

您可以在DOM 組件屬性列表中找到所有這些屬性。 如果您弄錯了一個,別擔心—React 會在瀏覽器控制台中印出一條訊息,其中包含可能的更正。

陷阱

由於歷史原因,aria-*data-* 屬性與 HTML 中一樣使用破折號編寫。

專業提示:使用 JSX 轉換器

在現有標記中轉換所有這些屬性可能很麻煩!我們建議使用轉換器將您現有的 HTML 和 SVG 翻譯成 JSX。轉換器在實踐中非常有用,但仍然值得了解發生了什麼事,以便您可以輕鬆地自行編寫 JSX。

這是你的最終結果

export default function TodoList() {
  return (
    <>
      <h1>Hedy Lamarr's Todos</h1>
      <img 
        src="https://i.imgur.com/yXOvdOSs.jpg" 
        alt="Hedy Lamarr" 
        className="photo" 
      />
      <ul>
        <li>Invent new traffic lights</li>
        <li>Rehearse a movie scene</li>
        <li>Improve the spectrum technology</li>
      </ul>
    </>
  );
}

摘要

現在您知道為什麼 JSX 存在以及如何在組件中使用它

  • React 組件將渲染邏輯與標記組合在一起,因為它們是相關的。
  • JSX 類似於 HTML,但有一些差異。如果需要,您可以使用轉換器
  • 錯誤訊息通常會指出您朝著修復標記的正確方向前進。

挑戰 1 1:
將一些 HTML 轉換為 JSX

這段 HTML 被貼到一個組件中,但它不是有效的 JSX。修復它

export default function Bio() {
  return (
    <div class="intro">
      <h1>Welcome to my website!</h1>
    </div>
    <p class="summary">
      You can find my thoughts here.
      <br><br>
      <b>And <i>pictures</b></i> of scientists!
    </p>
  );
}

是要手動完成還是使用轉換器取決於您!