导入和导出组件

组件的神奇之处在于其可重用性:你可以创建由其他组件组成的组件。但是,随着你嵌套越来越多的组件,将它们拆分成不同的文件通常更有意义。这使你可以轻松扫描文件并在更多地方重用组件。

你将学习

  • 什么是根组件文件
  • 如何导入和导出组件
  • 何时使用默认导入和导出以及命名导入和导出
  • 如何从一个文件中导入和导出多个组件
  • 如何将组件拆分成多个文件

根组件文件

你的第一个组件中,你创建了一个 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>
  );
}

这些目前位于一个名为 App.js根组件文件中(本例中)。但是,根据你的设置,你的根组件可能在另一个文件中。如果你使用基于文件的路由框架,例如 Next.js,那么每个页面的根组件都将不同。

导出和导入组件

如果你想将来更改登录屏幕并在那里放置一个科学书籍列表怎么办?或者将所有个人资料放在其他地方?将 GalleryProfile 从根组件文件中移出是有意义的。这将使它们在其他文件中更具模块化和可重用性。你可以分三个步骤移动组件

  1. 创建一个新的 JS 文件来放置组件。
  2. 导出你的函数组件(使用 默认命名导出)。
  3. 导入它到你将使用该组件的文件中(使用相应的 默认命名导入技术)。

这里 ProfileGallery 都已从 App.js 移动到一个名为 Gallery.js 的新文件中。现在你可以更改 App.js 以从 Gallery.js 导入 Gallery

import Gallery from './Gallery.js';

export default function App() {
  return (
    <Gallery />
  );
}

注意这个例子现在是如何分解成两个组件文件的。

  1. Gallery.js:
    • 定义仅在同一文件中使用且未导出的 Profile 组件。
    • Gallery 组件作为 默认导出导出。
  2. App.js:
    • Gallery.js 作为 默认导入导入 Gallery
    • 将根 App 组件作为 默认导出导出。

注意

你可能会遇到省略 .js 文件扩展名的文件,如下所示

import Gallery from './Gallery';

使用 React 时,'./Gallery.js''./Gallery' 都可以工作,但前者更接近原生 ES 模块 的工作方式。

深入探讨

默认导出与命名导出

JavaScript 主要有两种导出值的方式:默认导出和命名导出。到目前为止,我们的示例只使用了默认导出。但是你可以在同一个文件中同时使用两者。 一个文件最多只能有一个默认导出,但可以有多个命名导出。

Default and named exports

你如何导出组件决定了如何导入它。如果你尝试以与命名导出相同的方式导入默认导出,将会出错!此图表可以帮助你跟踪

语法导出语句导入语句
默认export default function Button() {}import Button from './Button.js';
命名export function Button() {}import { Button } from './Button.js';

当你编写默认导入时,你可以在import之后使用任何你想要的名称。例如,你可以编写import Banana from './Button.js',它仍然会提供相同的默认导出。相反,对于命名导入,两边的名称必须匹配。这就是为什么它们被称为命名导入!

如果文件只导出一个组件,人们通常使用默认导出;如果导出多个组件和值,则使用命名导出。 无论你偏好哪种编码风格,始终为组件函数和包含它们的文 件赋予有意义的名称。不带名称的组件,例如 export default () => {},是不鼓励的,因为它们会使调试更加困难。

从同一个文件导出和导入多个组件

如果你只想显示一个Profile而不是一个图库怎么办?你也可以导出Profile组件。但是Gallery.js已经有一个默认导出,你不能有两个默认导出。你可以创建一个带有默认导出的新文件,或者为Profile添加一个命名导出。一个文件只能有一个默认导出,但可以有多个命名导出!

注意

为了减少默认导出和命名导出之间的潜在混淆,一些团队选择只坚持一种风格(默认或命名),或者避免在一个文件中混合使用它们。选择最适合你的方式!

首先,导出 ProfileGallery.js 使用命名导出(无default关键字)

export function Profile() {
// ...
}

然后,导入 ProfileGallery.jsApp.js 使用命名导入(带花括号)

import { Profile } from './Gallery.js';

最后,渲染 <Profile />App 组件

export default function App() {
return <Profile />;
}

现在 Gallery.js 包含两个导出:一个默认 Gallery 导出和一个命名 Profile 导出。 App.js 导入两者。尝试在这个例子中将 <Profile />编辑为<Gallery />然后再改回。

import Gallery from './Gallery.js';
import { Profile } from './Gallery.js';

export default function App() {
  return (
    <Profile />
  );
}

现在你正在混合使用默认导出和命名导出。

  • Gallery.js:
    • Profile 组件导出为 名为 Profile 的命名导出。
    • Gallery 组件作为 默认导出导出。
  • App.js:
    • Gallery.js 导入 Profile 作为 名为 Profile 的命名导入。
    • Gallery.js 作为 默认导入导入 Gallery
    • 将根 App 组件作为 默认导出导出。

总结

在本页中,你学习了

  • 什么是根组件文件
  • 如何导入和导出组件
  • 何时以及如何使用默认导入和导出以及命名导入和导出
  • 如何从同一个文件导出多个组件

挑战 1 1:
进一步拆分组件

目前,Gallery.js同时导出ProfileGallery,这有点令人困惑。

将`Profile组件移动到它自己的`Profile.js文件中,然后修改`App组件,使其依次渲染`<Profile />和`<Gallery />

你可以对`Profile使用默认导出或命名导出,但请确保在`App.js和`Gallery.js中使用相应的导入语法!你可以参考上面深入讲解中的表格。

语法导出语句导入语句
默认export default function Button() {}import Button from './Button.js';
命名export function Button() {}import { Button } from './Button.js';
// Move me to Profile.js!
export function Profile() {
  return (
    <img
      src="https://i.imgur.com/QIrZWGIs.jpg"
      alt="Alan L. Hart"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

使用一种导出方式使其运行后,再尝试使用另一种导出方式。