在 JSX 中使用 JavaScript 的語法

JSX 讓你在 JavaScript 文件中撰寫類似 HTML 標籤的程式碼,使渲染邏輯和內容保持在同樣的地方。有時你會想在標籤中新增一些 JavaScript 邏輯或引用一個動態屬性。在這種情況下,你可以在 JSX 中使用大括號來撰寫 JavaScript。

You will learn

  • 如何使用引號傳遞 string
  • 如何使用大括號在 JSX 中引用 JavaScript 變數
  • 如何使用大括號在 JSX 中呼叫 JavaScript 函式
  • 如何使用大括號在 JSX 中使用 JavaScript object

使用引號傳遞 string

當你想向 JSX 傳遞一個 string attribute 時,你要把它放在單引號或雙引號中:

export default function Avatar() {
  return (
    <img
      className="avatar"
      src="https://i.imgur.com/7vQD0fPs.jpg"
      alt="Gregorio Y. Zara"
    />
  );
}

在這裡,"https://i.imgur.com/7vQD0fPs.jpg""Gregorio Y. Zara" 被作為 string 傳遞。

但是如果你想動態地指定 srcalt 內容呢?你可以替換""{},來使用 JavaScript 中的值:

export default function Avatar() {
  const avatar = 'https://i.imgur.com/7vQD0fPs.jpg';
  const description = 'Gregorio Y. Zara';
  return (
    <img
      className="avatar"
      src={avatar}
      alt={description}
    />
  );
}

注意 className="avatar"src={avatar} 之間的區別,前者指定了一個 "avatar" 的 CSS classname,使圖片變成圓形,而後者讀取了 JavaScript 變量 avatar 變數的值。這是因為大括號可以讓你在標籤中使用 JavaScript!

使用大括號: 進入 JavaScript 世界的窗口

JSX 是編寫 JavaScript 的一種特殊方式。這意味著可以在它裡面透過大括號 { } 使用 JavaScript。下面的範例首先宣告了一位科學家的名字 name ,然後用大括號將其嵌入 <h1> 內:

export default function TodoList() {
  const name = 'Gregorio Y. Zara';
  return (
    <h1>{name}'s To Do List</h1>
  );
}

試著把 name 的值從 Gregorio Y. Zara 改為 Hedy Lamarr。看到待辦事項列表的標題如何變化了嗎?

任何的 JavaScript 表達式都可以在大括號之間使用,包括呼叫像是 formatDate() 的函式:

const today = new Date();

function formatDate(date) {
  return new Intl.DateTimeFormat(
    'en-US',
    { weekday: 'long' }
  ).format(date);
}

export default function TodoList() {
  return (
    <h1>To Do List for {formatDate(today)}</h1>
  );
}

哪裡使用大括號

你只能在 JSX 中以兩種方式使用大括號。

  1. 作為文字 直接在 JSX 標籤內使用。 <h1>{name}'s To Do List</h1> 可以使用,但 <{tag}>Gregorio Y. Zara's To Do List</{tag}> 就不行。
  2. 作為 attributes 緊隨 = 符號之後:src={avatar} 將讀取 avatar 變數,但 src="{avatar}" 將傳遞 string "{avatar}"

使用 “雙引號”:JSX 中的 CSS 和其他 object

除了 string、number 和其他 JavaScript 表達式外,你甚至可以在 JSX 中傳遞 object。Object 也必須用大括號表示,如 { name: "Hedy Lamarr", inventions: 5 } 。因此,要在 JSX 中傳遞一個 JS object,你必須用另一對大括號包裹該 object:person={{ name: "Hedy Lamarr", inventions: 5 }}

你可能會在 JSX 中看到這種 inline CSS 樣式。 React 並不要求你使用 inline 樣式(CSS class 在大多數情況下運作的很好)。但是當你需要一個 inline 樣式時,你要向 style attribute 傳遞一個 object:

export default function TodoList() {
  return (
    <ul style={{
      backgroundColor: 'black',
      color: 'pink'
    }}>
      <li>Improve the videophone</li>
      <li>Prepare aeronautics lectures</li>
      <li>Work on the alcohol-fuelled engine</li>
    </ul>
  );
}

嘗試改變 backgroundColorcolor 的值。

當你這樣寫時,你清楚地看到大括號內的 JavaScript object。

<ul style={
{
backgroundColor: 'black',
color: 'pink'
}
}>

下次你在 JSX 中看到 {{}} 的時候,要知道它只不過是 JSX 大括號中的一個 object 而已!

Pitfall

Inline 的 style 屬性是用 camelCase 寫的。例如,HTML <ul style="background-color: black"> 在你的 component 中應該寫成 <ul style={{ backgroundColor: 'black' }}>

更多關於有趣的 JavaScript object 和大括號

你可以把幾個表達式移到一個 object 中,並在你的 JSX 中使用大括號引用它們。

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="https://i.imgur.com/7vQD0fPs.jpg"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}

在這個例子中,person 的 JavaScript object 包含一個 name string 和一個 theme object。

const person = {
name: 'Gregorio Y. Zara',
theme: {
backgroundColor: 'black',
color: 'pink'
}
};

該 component 可以像這樣使用這些來自 person 的值。

<div style={person.theme}>
<h1>{person.name}'s Todos</h1>

JSX 是非常簡潔的模板語言,因為它允許使用 JavaScript 來組織資料和邏輯。

Recap

現在你已經幾乎了解 JSX 的所有內容:

  • 在引號內的 JSX attributes 被傳遞為 string。
  • 大括號可以讓你將 JavaScript 邏輯和變數帶入標籤中。
  • 它們可以在 JSX 標籤內容內部或在屬性中的 = 後立即使用。
  • {{}} 不是特殊的語法:它是一個被包含在 JSX 大括號內的 JavaScript object。

Challenge 1 of 3:
糾正錯誤

這段代碼會崩潰並報錯 Objects are not valid as a React child

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person}'s Todos</h1>
      <img
        className="avatar"
        src="https://i.imgur.com/7vQD0fPs.jpg"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}

你能找到問題所在嗎?