使用 JSX 编写标记

JSX 是 JavaScript 的语法扩展,可让你在 JavaScript 文件中编写类似 HTML 的标记。尽管还有其他方式来编写组件,但大多数 React 开发者更喜欢 JSX 的简洁性,并且大多数代码库都使用它。

¥JSX is a syntax extension for JavaScript that lets you write HTML-like markup inside a JavaScript file. Although there are other ways to write components, most React developers prefer the conciseness of JSX, and most codebases use it.

你将学习到

  • 为什么 React 将标记与渲染逻辑混合在一起

    ¥Why React mixes markup with rendering logic

  • JSX 与 HTML 有何不同

    ¥How JSX is different from HTML

  • 如何用 JSX 显示信息

    ¥How to display information with JSX

JSX:将标记放入 JavaScript 中

¥JSX: Putting markup into JavaScript

Web 是建立在 HTML、CSS 和 JavaScript 之上的。多年来,Web 开发者将内容保存在 HTML 中,设计保存在 CSS 中,逻辑保存在 JavaScript 中 - 通常保存在单独的文件中!内容在 HTML 中标记,而页面的逻辑在 JavaScript 中单独存在:

¥The Web has been built on HTML, CSS, and JavaScript. For many years, web developers kept content in HTML, design in CSS, and logic in JavaScript—often in separate files! Content was marked up inside HTML while the page’s logic lived separately in 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 中,渲染逻辑和标记一起存在于同一个地方 - 组件。

¥But as the Web became more interactive, logic increasingly determined content. JavaScript was in charge of the HTML! This is why in React, rendering logic and markup live together in the same place—components.

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 组件

将按钮的渲染逻辑和标记放在一起可确保它们在每次编辑时都保持同步。反之,不相关的细节(例如按钮的标记和侧边栏的标记)彼此隔离,从而更安全地自行更改其中任何一个。

¥Keeping a button’s rendering logic and markup together ensures that they stay in sync with each other on every edit. Conversely, details that are unrelated, such as the button’s markup and a sidebar’s markup, are isolated from each other, making it safer to change either of them on their own.

每个 React 组件都是一个 JavaScript 函数,其中可能包含 React 渲染到浏览器中的一些标记。React 组件使用称为 JSX 的语法扩展来表示该标记。JSX 看起来很像 HTML,但更严格一些,并且可以显示动态信息。理解这一点的最好方法是将一些 HTML 标记转换为 JSX 标记。

¥Each React component is a JavaScript function that may contain some markup that React renders into the browser. React components use a syntax extension called JSX to represent that markup. JSX looks a lot like HTML, but it is a bit stricter and can display dynamic information. The best way to understand this is to convert some HTML markup to JSX markup.

注意

JSX 和 React 是两个独立的东西。它们经常一起使用,但你可以互相 独立使用它们。JSX 是一个语法扩展,而 React 是一个 JavaScript 库。

¥JSX and React are two separate things. They’re often used together, but you can use them independently of each other. JSX is a syntax extension, while React is a JavaScript library.

将 HTML 转换为 JSX

¥Converting HTML to JSX

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

¥Suppose that you have some (perfectly valid) 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>

你想把它放到你的组件中:

¥And you want to put it into your component:

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

如果你按原样复制并粘贴它,它将不起作用:

¥If you copy and paste it as is, it will not work:

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 更严格并且有更多的规则!如果你阅读了上面的错误消息,它们会指导你修复标记,或者你可以按照下面的指南进行操作。

¥This is because JSX is stricter and has a few more rules than HTML! If you read the error messages above, they’ll guide you to fix the markup, or you can follow the guide below.

注意

大多数时候,React 的屏幕错误消息会帮助你找到问题所在。如果你遇到困难,请读一读!

¥Most of the time, React’s on-screen error messages will help you find where the problem is. Give them a read if you get stuck!

JSX 规则

¥The Rules of JSX

1. 返回单个根元素

¥ Return a single root element

要从组件返回多个元素,请使用单个父标签封装它们。

¥To return multiple elements from a component, wrap them with a single parent tag.

例如,你可以使用 <div>

¥For example, you can use a <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>,你可以改为编写 <></>

¥If you don’t want to add an extra <div> to your markup, you can write <> and </> instead:

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

这个空标签称为 片段。片段让你可以对内容进行分组,而不会在浏览器 HTML 树中留下任何痕迹。

¥This empty tag is called a Fragment. Fragments let you group things without leaving any trace in the browser HTML tree.

深入研究

为什么需要封装多个 JSX 标签?

¥Why do multiple JSX tags need to be wrapped?

JSX 看起来像 HTML,但在底层它被转换为普通的 JavaScript 对象。如果不将它们封装到数组中,则不能从函数返回两个对象。这解释了为什么你也不能返回两个 JSX 标签而不将它们封装到另一个标签或片段中。

¥JSX looks like HTML, but under the hood it is transformed into plain JavaScript objects. You can’t return two objects from a function without wrapping them into an array. This explains why you also can’t return two JSX tags without wrapping them into another tag or a Fragment.

2. 关闭所有标签

¥ Close all the tags

JSX 要求标记被显式闭合:像 <img> 这样的自闭标签一定要写成 <img />,像 <li>oranges 这样的环绕标签一定要写成 <li>oranges</li>

¥JSX requires tags to be explicitly closed: self-closing tags like <img> must become <img />, and wrapping tags like <li>oranges must be written as <li>oranges</li>.

Hedy Lamarr 的图片和列表项看起来是这样闭合的:

¥This is how Hedy Lamarr’s image and list items look closed:

<>
<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 all most of the things!

JSX 变成 JavaScript,用 JSX 写的属性变成 JavaScript 对象的键。在你自己的组件中,你通常希望将这些属性读入变量。但是 JavaScript 对变量名有限制。例如,它们的名称不能包含破折号或像 class 这样的保留字。

¥JSX turns into JavaScript and attributes written in JSX become keys of JavaScript objects. In your own components, you will often want to read those attributes into variables. But JavaScript has limitations on variable names. For example, their names can’t contain dashes or be reserved words like class.

这就是为什么在 React 中,许多 HTML 和 SVG 属性都是用驼峰式命名的。例如,你使用 strokeWidth 而不是 stroke-width。因为 class 是一个保留字,在 React 中你写成 className,以 相应的 DOM 属性 命名:

¥This is why, in React, many HTML and SVG attributes are written in camelCase. For example, instead of stroke-width you use strokeWidth. Since class is a reserved word, in React you write className instead, named after the corresponding DOM property:

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

你可以 在 DOM 组件属性列表中找到所有这些属性 如果你弄错了,别担心 - React 会打印一条消息,并可能对 浏览器控制台 进行更正

¥You can find all these attributes in the list of DOM component props. If you get one wrong, don’t worry—React will print a message with a possible correction to the browser console.

易犯错误

由于历史原因,aria-*data-* 属性在 HTML 中用破折号书写。

¥For historical reasons, aria-* and data-* attributes are written as in HTML with dashes.

专业提示:使用 JSX 转换器

¥Pro-tip: Use a JSX Converter

转换现有标记中的所有这些属性可能很乏味!我们建议使用 转换器 将现有的 HTML 和 SVG 转换为 JSX。转换器在实践中非常有用,但仍然值得了解发生了什么,这样你就可以轻松地自己编写 JSX。

¥Converting all these attributes in existing markup can be tedious! We recommend using a converter to translate your existing HTML and SVG to JSX. Converters are very useful in practice, but it’s still worth understanding what is going on so that you can comfortably write JSX on your own.

这是你的最终结果:

¥Here is your final result:

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 存在以及如何在组件中使用它了:

¥Now you know why JSX exists and how to use it in components:

  • React 组件将渲染逻辑与标记组合在一起,因为它们是相关的。

    ¥React components group rendering logic together with markup because they are related.

  • JSX 类似于 HTML,但有一些不同。如果需要,你可以使用 转换器

    ¥JSX is similar to HTML, with a few differences. You can use a converter if you need to.

  • 错误消息通常会为你指明修复标记的正确方向。

    ¥Error messages will often point you in the right direction to fixing your markup.

挑战 1 / 1:
将一些 HTML 转换为 JSX

¥Convert some HTML to JSX

此 HTML 已粘贴到组件中,但它不是有效的 JSX。修复它:

¥This HTML was pasted into a component, but it’s not valid JSX. Fix it:

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>
  );
}

是手动还是使用转换器由你决定!

¥Whether to do it by hand or using the converter is up to you!


React 中文网 - 粤ICP备13048890号