组件的导入与导出:根组件与多组件文件拆分
在上一关中,我们把 Profile 和 Gallery 两个组件写在了同一个文件里。当应用只有两三个小组件时,这很方便。但随着页面功能扩展,一个文件如果堆砌了几千行代码,寻找和维护就会变得极其痛苦。
React 完全基于现代 JavaScript(ES6)的模块系统。你可以把每个组件提取到它自己的独立文件中,再通过 import 和 export 自由拼装。
1. 根组件文件(The Root Component File)
在绝大多数基于 React 构建的应用中,都会有一个“起点”,它被称为 根组件(Root Component)。
- 在 Next.js 或 Vite 等现代工具中,通常是
App.js、App.tsx或page.js; - 根组件负责作为整个应用的最顶层容器,将其他所有子组件像树枝一样层层容纳进来。
2. 将组件拆分到独立文件
让我们把上一关的 Profile 和 Gallery 拆分到两个文件中。
步骤一:创建新文件并导出子组件
创建一个名为 Profile.js 的新文件,把 Profile 移进去,并使用 export default 导出:
// Profile.js
export default function Profile() {
return (
<img
src="https://i.imgur.com/MK3eW3As.jpg"
alt="Katherine Johnson"
/>
);
}
步骤二:在目标文件中导入并使用
在 Gallery.js(或者 App.js)的顶部,使用 import 关键字导入该组件:
// Gallery.js
import Profile from './Profile.js';
export default function Gallery() {
return (
<section>
<h1>了不起的科学家们</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
语法说明:
./Profile.js:./表示“当前目录下的同级文件”。- 在许多现代打包工具中,
.js后缀可以省略,写作import Profile from './Profile';。
3. 默认导出(Default)与具名导出(Named)
JavaScript 提供了两种导出方式,它们在语法和使用场景上有明显区别:
| 导出方式 | 导出语法 | 导入语法 | 一个文件允许数量 |
|---|---|---|---|
| 默认导出 (Default) | export default function Button() {} | import Button from './Button.js';(无花括号) | 仅限 1 个 |
| 具名导出 (Named) | export function Button() {} | import { Button } from './Button.js';(必须有花括号) | 可以有多个 |
具名导出示例
一个文件有时需要同时向外提供多个辅助组件或小工具:
// Buttons.js
export function PrimaryButton() {
return <button className="btn-primary">主要按钮</button>;
}
export function SecondaryButton() {
return <button className="btn-secondary">次要按钮</button>;
}
在导入时,必须使用花括号将名称括起来:
// App.js
import { PrimaryButton, SecondaryButton } from './Buttons.js';
默认导出与重命名的灵活性
使用默认导出时,导入方可以自由给组件起别名(虽然为了可读性通常保持同名):
// 即使 Profile.js 里叫 Profile,导入时也可以叫 MyProfile
import MyProfile from './Profile.js';
而具名导出时,名称必须严格匹配,或者显式使用 as 重命名(import { PrimaryButton as MainBtn } ...)。
4. 同一个文件同时使用两种导出
很多组件库会采用这种模式:主组件作为默认导出,相关的辅助组件作为具名导出:
// Gallery.js
export function Profile() {
return <img src="..." alt="..." />;
}
export default function Gallery() {
return (
<div>
<Profile />
</div>
);
}
在另一个文件中,你可以一行代码同时导入它们:
import Gallery, { Profile } from './Gallery.js';
(注意:没有花括号的 Gallery 对应默认导出,花括号里的 Profile 对应具名导出)。
总结
- 复杂的单文件应该拆分为高内聚、易于阅读的独立模块;
- 一个文件只能有一个默认导出(
export default),导入时无需花括号; - 一个文件可以有多个具名导出(
export),导入时必须使用花括号{ ... }; - 模块拆分让团队协作与代码测试变得清晰简单。