The magic of components lies in their reusability: you can create components that are composed of other components. But as you nest more and more components, it often makes sense to start splitting them into different files. This lets you keep your files easy to scan and reuse components in more places. 组件的神奇之处在于它们的可重用性:你可以创建一个由其他组件构成的组件。但当你嵌套了越来越多的组件时,则需要将它们拆分成不同的文件。这样可以使得查找文件更加容易,并且能在更多地方复用这些组件。
你将会学习到
- What a root component file is
- 何为根组件
- How to import and export a component
- 如何导入和导出一个组件
- When to use default and named imports and exports
- 何时使用默认和具名导入导出
- How to import and export multiple components from one file
- 如何在一个文件中导入导出多个组件
- How to split components into multiple files
- 如何将组件拆分成多个文件
根组件文件 | The root component file
In Your First Component, you made a Profile
component and a Gallery
component that renders it:
在 你的第一个组件 中,你创建了一个 Profile
组件,并且渲染在 Gallery
组件里。
function Profile() { return ( <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" /> ); } export default function Gallery() { return ( <section> <h1>了不起的科学家们</h1> <Profile /> <Profile /> <Profile /> </section> ); }
These currently live in a root component file, named App.js
in this example. Depending on your setup, your root component could be in another file, though. If you use a framework with file-based routing, such as Next.js, your root component will be different for every page.
在此示例中,所有组件目前都定义在 根组件 App.js
文件中。具体还需根据项目配置决定,有些根组件可能会声明在其他文件中。如果你使用的框架基于文件进行路由,如 Next.js,那你每个页面的根组件都会不一样。
导出和导入一个组件 | Exporting and importing a component
What if you want to change the landing screen in the future and put a list of science books there? Or place all the profiles somewhere else? It makes sense to move Gallery
and Profile
out of the root component file. This will make them more modular and reusable in other files. You can move a component in three steps:
如果将来需要在首页添加关于科学书籍的列表,亦或者需要将所有的资料信息移动到其他文件。这时将 Gallery
组件和 Profile
组件移出根组件文件会更加合理。这会使组件更加模块化,并且可在其他文件中复用。你可以根据以下三个步骤对组件进行拆分:
- Make a new JS file to put the components in.
- 创建 一个新的 JS 文件来存放该组件。
- Import it in the file where you’ll use the component (using the corresponding technique for importing default or named exports).
Here both Profile
and Gallery
have been moved out of App.js
into a new file called Gallery.js
. Now you can change App.js
to import Gallery
from Gallery.js
:
这里将 Profile
组件和 Gallery
组件,从 App.js
文件中移动到了 Gallery.js
文件中。修改后,即可在 App.js
中导入 Gallery.js
中的 Gallery
组件:
import Gallery from './Gallery.js'; export default function App() { return ( <Gallery /> ); }
Notice how this example is broken down into two component files now: 该示例中需要注意的是,如何将组件拆分成两个文件:
Gallery.js
:
Gallery.js
:- Defines the
Profile
component which is only used within the same file and is not exported. - 定义了
Profile
组件,该组件仅在该文件内使用,没有被导出。 - Exports the
Gallery
component as a default export. - 使用 默认导出 的方式,将
Gallery
组件导出
- Defines the
App.js
:
App.js
:- Imports
Gallery
as a default import fromGallery.js
. - 使用 默认导入 的方式,从
Gallery.js
中导入Gallery
组件。 - Exports the root
App
component as a default export. - 使用 默认导出 的方式,将根组件
App
导出。
- Imports
深入探讨
There are two primary ways to export values with JavaScript: default exports and named exports. So far, our examples have only used default exports. But you can use one or both of them in the same file. A file can have no more than one default export, but it can have as many named exports as you like. 这是 JavaScript 里两个主要用来导出值的方式:默认导出和具名导出。到目前为止,我们的示例中只用到了默认导出。但你可以在一个文件中,选择使用其中一种,或者两种都使用。一个文件里有且仅有一个 默认 导出,但是可以有任意多个 具名 导出。
How you export your component dictates how you must import it. You will get an error if you try to import a default export the same way you would a named export! This chart can help you keep track: 组件的导出方式决定了其导入方式。当你用默认导入的方式,导入具名导出的组件时,就会报错。如下表格可以帮你更好地理解它们:
语法/Syntax | 导出语句/Export statement | 导入语句/Import statement |
---|---|---|
默认/Default | export default function Button() {} | import Button from './Button.js'; |
具名/Named | export function Button() {} | import { Button } from './Button.js'; |
When you write a default import, you can put any name you want after import
. For example, you could write import Banana from './Button.js'
instead and it would still provide you with the same default export. In contrast, with named imports, the name has to match on both sides. That’s why they are called named imports!
当使用默认导入时,你可以在 import
语句后面进行任意命名。比如 import Banana from './Button.js'
,如此你能获得与默认导出一致的内容。相反,对于具名导入,导入和导出的名字必须一致。这也是称其为 具名 导入的原因!
People often use default exports if the file exports only one component, and use named exports if it exports multiple components and values. Regardless of which coding style you prefer, always give meaningful names to your component functions and the files that contain them. Components without names, like export default () => {}
, are discouraged because they make debugging harder.
通常,文件中仅包含一个组件时,人们会选择默认导出,而当文件中包含多个组件或某个值需要导出时,则会选择具名导出。 无论选择哪种方式,请记得给你的组件和相应的文件命名一个有意义的名字。我们不建议创建未命名的组件,比如 export default () => {}
,因为这样会使得调试变得异常困难。
从同一文件中导出和导入多个组件 | Exporting and importing multiple components from the same file
What if you want to show just one Profile
instead of a gallery? You can export the Profile
component, too. But Gallery.js
already has a default export, and you can’t have two default exports. You could create a new file with a default export, or you could add a named export for Profile
. A file can only have one default export, but it can have numerous named exports!
如果你只想展示一个 Profile
组,而不展示整个图集。你也可以导出 Profile
组件。但 Gallery.js
中已包含 默认 导出,此时,你不能定义 两个 默认导出。但你可以将其在新文件中进行默认导出,或者将 Profile
进行 具名 导出。同一文件中,有且仅有一个默认导出,但可以有多个具名导出!
First, export Profile
from Gallery.js
using a named export (no default
keyword):
首先,用具名导出的方式,将 Profile
组件从 Gallery.js
导出(不使用 default
关键字):
export function Profile() {
// ...
}
Then, import Profile
from Gallery.js
to App.js
using a named import (with the curly braces):
接着,用具名导入的方式,从 Gallery.js
文件中 导入 Profile
组件(用大括号):
import { Profile } from './Gallery.js';
Finally, render <Profile />
from the App
component:
最后,在 App
组件里 渲染 <Profile />
:
export default function App() {
return <Profile />;
}
Now Gallery.js
contains two exports: a default Gallery
export, and a named Profile
export. App.js
imports both of them. Try editing <Profile />
to <Gallery />
and back in this example:
现在,Gallery.js
包含两个导出:一个是默认导出的 Gallery
,另一个是具名导出的 Profile
。App.js
中均导入了这两个组件。尝试将 <Profile />
改成 <Gallery />
,回到示例中:
import Gallery from './Gallery.js'; import { Profile } from './Gallery.js'; export default function App() { return ( <Profile /> ); }
Now you’re using a mix of default and named exports: 示例中混合使用了默认导出和具名导出:
Gallery.js
:- Exports the
Profile
component as a named export calledProfile
. - 使用 具名导出 的方式,将
Profile
组件导出,并取名为Profile
。 - Exports the
Gallery
component as a default export. - 使用 默认导出 的方式,将
Gallery
组件导出。
- Exports the
App.js
:- Imports
Profile
as a named import calledProfile
fromGallery.js
. - 使用 具名导入 的方式,从
Gallery.js
中导入Profile
组件,并取名为Profile
。 - Imports
Gallery
as a default import fromGallery.js
. - 使用 默认导入 的方式,从
Gallery.js
中导入Gallery
组件。 - Exports the root
App
component as a default export. - 使用 默认导出 的方式,将根组件
App
导出。
- Imports
摘要
On this page you learned: 在本章节中,你学到了:
- What a root component file is
- 何为根组件
- How to import and export a component
- 如何导入和导出一个组件
- When and how to use default and named imports and exports
- 何时和如何使用默认和具名导入导出
- How to export multiple components from the same file
- 如何在一个文件里导出多个组件
第 1 个挑战 共 1 个挑战: 进一步拆分组件 | Split the components further
Currently, Gallery.js
exports both Profile
and Gallery
, which is a bit confusing.
现在,Gallery.js
同时导出了 Profile
和 Gallery
,这会让人感到有点混淆。
Move the Profile
component to its own Profile.js
, and then change the App
component to render both <Profile />
and <Gallery />
one after another.
尝试将 Profile
组件移动到 Profile.js
文件中,然后更新 App
组件,依次渲染 <Profile />
和 <Gallery />
。
You may use either a default or a named export for Profile
, but make sure that you use the corresponding import syntax in both App.js
and Gallery.js
! You can refer to the table from the deep dive above:
你也许会使用默认导出或者具名导出的方式,来导出 Profile
组件,但请保证在 App.js
和 Gallery.js
里使用相应的导入语句!具体可以参考下面的表格:
语法/Syntax | 导出语句/Export statement | 导入语句/Import statement |
---|---|---|
默认/Default | export default function Button() {} | import Button from './Button.js'; |
具名/Named | 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>了不起的科学家们</h1> <Profile /> <Profile /> <Profile /> </section> ); }
After you get it working with one kind of exports, make it work with the other kind. 当你使用其中一种导出方式完成以上任务后,请尝试使用另一种导出方式实现。