编写你的第一个组件

组件(Components)是 React 的核心概念之一。它是构建用户界面(UI)的基石,因此,对组件的学习成为你 React 旅程中完美的第一站!

You will learn

  • 组件(component)是什么
  • 组件在 React 应用程序中扮演着什么样的角色
  • 如何编写你的第一个 React 组件

组件(Components):用户界面(UI)的构建块

在网站上,HTML 为我们提供了许多创建丰富的结构化文档的内置标签(tags),例如 <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> 列出的目录。像这样的 markup,并结合 CSS 用于描绘样式以及 JavaScript 增加交互能力,构成了所有网站 UI 上的侧边栏(sidebar)、头像(avatar)、模态框(modal)、下拉菜单(dropdown)等组成部分。

React 赋予你将标记(markup)、CSS 和 JavaScript 组合成自定义的 “组件(components)” 的能力,也就是 针对你的应用程序的可重用 UI 元素。 你在上面看到的目录代码可以变成一个 <TableOfContents /> 组件,并渲染到每个页面上。其底层,仍然是使用的相同的 HTML 标签(tags),例如 <article><h1> 等。

就像 HTML 的标签(tags)一样,你可以组合、排序以及嵌套组件来组成整个页面。例如,你正在阅读的这份文档就是由以下这些 React 组件组成的:

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

随着项目的发展,你会注意到许多设计都可以通过重用你已经编写的组件来完成,从而提升开发速度。我们上面示例中的目录可以在任何使用了 <TableOfContents /> 组件的页面上渲染!你甚至可以使用 React 开源社区中(例如 Chakra UIMaterial UI)所共享的数千个组件来快速启动你的项目。

定义组件

传统意义上,在创建网页时,web 开发人员会通过对内容做标记,然后添加一些 JavaScript 代码实现交互功能。当网站上的这种交互是“有比没有强”时,这种方式很不错。但是,现在许多网站和所有的应用程序都需要添加交互能力,这种方式就很落后了。React 将交互性放在第一位,同时仍然使用了与以前相同的技术:一个 React 组件就是一个 JavaScript 函数,并且你可以在函数中 书写 markup。以下就是一个示例(你可以编辑):

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

下面讲解如何构建一个组件:

第一步:导出(export)组件

export default 前缀时一个 标准的 JavaScript 语法 (并非 React 专用)。改语法用于在文件中标记主函数(main function)以便将来在其它文件中导入(import)该函数。(更多相关信息请参考 导入(import)和导出(export)组件 章节!)

第二部:定义函数

通过 function Profile() { } 形式,你定义了一个名为 Profile 的 JavaScript 函数。

Pitfall

React 组件就是普通的 JavaScript 函数,但 函数名必须以大写字母开头,否则将无法正常使用!

第三步:添加 markup

该组件返回一个 <img /> 标签(tag),并带有 srcalt 属性。<img /> 从书写上看和 HTML 的标签是一样的,但实际上,它在底层是 JavaScript!这种语法被称为 JSX,它赋予你在 JavaScript 种书写 markup 的能力。

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

Pitfall

如果不写圆括号,return 后面的所有代码行 将被忽略

使用组件

现在已经定义了 Profile 组件,你可以将其嵌套到其它组件中了。例如,你可以导出(export)一个包含多个 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>

组件的嵌套和组织结构

组件(Components)就是普通的 JavaScript 函数,因此可以在同一个文件中定义多个组件。当组件相对较小或彼此紧密相关时,放在一起就非常方便。但是,如果文件变得很臃肿了,你就需要将 Profile 组件放到单独的文件中了。你将在 导入(import)与导出(export)组件 章节了解到如何操作。

由于 Profile 组件在 Gallery 组件中渲染,甚至渲染了多次,我们可以说 Gallery 是一个 父组件(parent component), 将每个 Profile 渲染为一个 “子组件(child component)“。这是 React 的神奇之处:你可以定义一个组件,然后在任意多个位置使用多次。

Deep Dive

Components All the Way Down

Recap

你刚刚对 React 有了一些初步的认识。接下来我们回顾一下要点。

  • React 赋予你创建 可重用的 UI 元素 的能力。

  • 在 React 应用程序中,每个 UI 部分都是一个组件。

  • React 组件是普通的 JavaScript 函数,并且:

    1. 函数名的首字母大写。
    2. 返回值是 JSX markup。

Challenge 1 of 4:
导出(export)组件

下面这个代码沙盒并不能运行,因为没有导出(export)根组件:

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

再查看答案之前,请尝试自己修复它!