导入和导出组件

组件的魔力在于它们的可重用性:您可以创建由其他组件组成的组件。但是,当您嵌套越来越多的组件时,通常最好将它们拆分到不同的文件中。这可以让您保持文件易于扫描并在更多地方重用组件。

你将学到

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

根组件文件

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

'./Gallery.js''./Gallery' 都可以与 React 一起使用,但前者更接近原生 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 添加命名导出。 一个文件只能有一个默认导出,但可以有多个命名导出!

注意

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

首先,使用命名导出(不带 default 关键字)从 Gallery.js导出 Profile

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

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

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

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

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

在您使用一种导出方式使其正常工作后,请尝试使用另一种导出方式使其也能正常工作。