组件是 React 的核心概念之一。它们是构建用户界面(UI)的基础,因此是开始学习 React 的理想起点!
你将学习到
- 什么是组件
- 组件在 React 应用中扮演什么角色
- 如何编写你的第一个 React 组件
组件:用户界面构建块
🌐 Components: UI building blocks
在网络上,HTML 让我们能够使用其内置的一套标签(如 <h1> 和 <li>)创建丰富的结构化文档:
🌐 On the Web, HTML lets us create rich structured documents with its built-in set of tags like <h1> and <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,构成了每个侧边栏、头像、模态窗口、下拉菜单——你在网页上看到的每一块用户界面背后的基础。
🌐 This markup represents this article <article>, its heading <h1>, and an (abbreviated) table of contents as an ordered list <ol>. Markup like this, combined with CSS for style, and JavaScript for interactivity, lies behind every sidebar, avatar, modal, dropdown—every piece of UI you see on the Web.
React 让你将标记、CSS 和 JavaScript 组合成自定义“组件”,可重用的应用界面元素。 上面看到的目录代码可以被转换成一个 <TableOfContents /> 组件,你可以在每个页面上渲染它。在底层,它仍然使用相同的 HTML 标签,如 <article>、<h1> 等。
🌐 React lets you combine your markup, CSS, and JavaScript into custom “components”, reusable UI elements for your app. The table of contents code you saw above could be turned into a <TableOfContents /> component you could render on every page. Under the hood, it still uses the same HTML tags like <article>, <h1>, etc.
就像使用 HTML 标签一样,你可以组合、排序和嵌套组件来设计整个页面。例如,你正在阅读的文档页面就是由 React 组件构成的:
🌐 Just like with HTML tags, you can compose, order and nest components to design whole pages. For example, the documentation page you’re reading is made out of React components:
<PageLayout>
<NavigationHeader>
<SearchBar />
<Link to="/docs">Docs</Link>
</NavigationHeader>
<Sidebar />
<PageContent>
<TableOfContents />
<DocumentationText />
</PageContent>
</PageLayout>随着你的项目不断发展,你会注意到许多设计可以通过重用你已经编写的组件来组合,从而加快开发速度。我们上面的目录可以使用 <TableOfContents /> 添加到任何屏幕上!你甚至可以利用 React 开源社区共享的成千上万的组件来快速启动你的项目,例如 Chakra UI 和 Material UI。
🌐 As your project grows, you will notice that many of your designs can be composed by reusing components you already wrote, speeding up your development. Our table of contents above could be added to any screen with <TableOfContents />! You can even jumpstart your project with the thousands of components shared by the React open source community like Chakra UI and Material UI.
定义组件
🌐 Defining a component
传统上,在创建网页时,网页开发者会先为他们的内容进行标记,然后通过加入一些 JavaScript 来增加交互功能。当交互在网页上只是锦上添花时,这种方法效果很好。现在,对于许多网站和所有应用来说,交互是必须的。React 把交互性放在首位,同时仍然使用相同的技术:React 组件是一个 JavaScript 函数,你可以在其中加入标记。 下面是示例(你可以编辑下面的例子):
🌐 Traditionally when creating web pages, web developers marked up their content and then added interaction by sprinkling on some JavaScript. This worked great when interaction was a nice-to-have on the web. Now it is expected for many sites and all apps. React puts interactivity first while still using the same technology: a React component is a JavaScript function that you can sprinkle with markup. Here’s what that looks like (you can edit the example below):
export default function Profile() { return ( <img src="https://i.imgur.com/MK3eW3Am.jpg" alt="Katherine Johnson" /> ) }
以下是构建组件的方法:
🌐 And here’s how to build a component:
步骤 1:导出组件
🌐 Step 1: Export the component
export default 前缀是一个 标准 JavaScript 语法(不是 React 特有的)。它允许你在文件中标记主函数,以便你以后可以从其他文件导入它。(关于导入的更多信息,请参见 导入和导出组件!)
🌐 The export default prefix is a standard JavaScript syntax (not specific to React). It lets you mark the main function in a file so that you can later import it from other files. (More on importing in Importing and Exporting Components!)
步骤 2:定义函数
🌐 Step 2: Define the function
使用 function Profile() { },你可以定义一个名为 Profile 的 JavaScript 函数。
🌐 With function Profile() { } you define a JavaScript function with the name Profile.
步骤 3:添加标记
🌐 Step 3: Add markup
该组件返回一个带有 src 和 alt 属性的 <img /> 标签。<img /> 的书写方式像 HTML,但实际上它在底层是 JavaScript!这种语法叫做 JSX,它允许你在 JavaScript 中嵌入标记。
🌐 The component returns an <img /> tag with src and alt attributes. <img /> is written like HTML, but it is actually JavaScript under the hood! This syntax is called JSX, and it lets you embed markup inside JavaScript.
返回语句可以全部写在一行中,就像在这个组件中一样:
🌐 Return statements can be written all on one line, as in this component:
return <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />;但是,如果你的标记不与 return 关键字在同一行上,你必须将其用一对括号括起来:
🌐 But if your markup isn’t all on the same line as the return keyword, you must wrap it in a pair of parentheses:
return (
<div>
<img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />
</div>
);使用组件
🌐 Using a component
既然你已经定义了你的 Profile 组件,你可以将它嵌套在其他组件中。例如,你可以导出一个使用多个 Profile 组件的 Gallery 组件:
🌐 Now that you’ve defined your Profile component, you can nest it inside other components. For example, you can export a Gallery component that uses multiple Profile components:
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> ); }
浏览器看到的
🌐 What the browser sees
注意外壳的区别:
🌐 Notice the difference in casing:
<section>是小写的,所以 React 知道我们指的是一个 HTML 标签。<Profile />以大写字母P开头,因此 React 知道我们想使用名为Profile的组件。
而 Profile 包含更多的 HTML:<img />。最终,浏览器看到的是:
🌐 And Profile contains even more HTML: <img />. In the end, this is what the browser sees:
<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
组件是常规的 JavaScript 函数,因此你可以在同一个文件中保留多个组件。当组件相对较小或彼此紧密相关时,这很方便。如果这个文件变得拥挤,你可以随时将 Profile 移动到一个单独的文件中。你将在不久后通过关于导入的页面学习如何做这件事。
🌐 Components are regular JavaScript functions, so you can keep multiple components in the same file. This is convenient when components are relatively small or tightly related to each other. If this file gets crowded, you can always move Profile to a separate file. You will learn how to do this shortly on the page about imports.
因为 Profile 组件被渲染在 Gallery 内——甚至渲染了好几次!——我们可以说 Gallery 是一个**父组件,**将每个 Profile 渲染为“子组件”。这是 React 的魔力之一:你可以定义一个组件一次,然后在任意地方、多次使用它。
🌐 Because the Profile components are rendered inside Gallery—even several times!—we can say that Gallery is a parent component, rendering each Profile as a “child”. This is part of the magic of React: you can define a component once, and then use it in as many places and as many times as you like.
深入研究
🌐 Components all the way down
你的 React 应用从一个“根”组件开始。通常,当你启动一个新项目时,它会自动创建。例如,如果你使用 CodeSandbox 或者使用框架 Next.js,根组件是在 pages/index.js 中定义的。在这些例子中,你一直在导出根组件。
🌐 Your React application begins at a “root” component. Usually, it is created automatically when you start a new project. For example, if you use CodeSandbox or if you use the framework Next.js, the root component is defined in pages/index.js. In these examples, you’ve been exporting root components.
大多数 React 应用在各个层面上都使用组件。这意味着你不仅会将组件用于可重用的部分,比如按钮,还会用于更大的部分,比如侧边栏、列表,最终甚至是完整的页面!组件是一种组织 UI 代码和标记的方便方式,即使其中有些组件只使用一次。
🌐 Most React apps use components all the way down. This means that you won’t only use components for reusable pieces like buttons, but also for larger pieces like sidebars, lists, and ultimately, complete pages! Components are a handy way to organize UI code and markup, even if some of them are only used once.
基于 React 的框架 更进一步。它们不仅使用一个空的 HTML 文件并让 React “接管”用 JavaScript 管理页面,它们还从你的 React 组件自动生成 HTML。这使你的应用在 JavaScript 代码加载之前就能显示一些内容。
尽管如此,许多网站仍然仅使用 React 来为现有的 HTML 页面添加交互性。它们有许多根组件,而不是为整个页面使用单一根组件。你可以根据需要使用多或少的 React。
🌐 Still, many websites only use React to add interactivity to existing HTML pages. They have many root components instead of a single one for the entire page. You can use as much—or as little—React as you need.
回顾
你刚刚体验了 React 的初步使用!让我们回顾一些关键点。
🌐 You’ve just gotten your first taste of React! Let’s recap some key points.
- React 让你可以创建组件,可在你的应用中重复使用的用户界面元素。
- 在 React 应用中,每一块 UI 都是一个组件。
- React 组件是常规的 JavaScript 函数,除了:
- 它们的名称总是以大写字母开头。
- 它们返回 JSX 标记。