React中组件的神奇之处在于它们的可重用性:你可以创建一个由其他组件构成的组件。但当你嵌套了越来越多的组件时,则需要将它们拆分成不同的文件。这样可以使得查找文件更加容易,并且能在更多地方复用这些组件。
导出组件
这是 JavaScript 里两个主要用来导出值的方式:默认导出和具名导出。到目前为止,我们的示例中只用到了默认导出。但你可以在一个文件中,选择使用其中一种,或者两种都使用。一个文件里有且仅有一个 默认 导出,但是可以有任意多个 具名 导出。
组件的导出方式决定了其导入方式。当你用默认导入的方式,导入具名导出的组件时,就会报错。如下表格可以帮你更好地理解它们:
| 语法 | 导出语句 | 导入语句 |
|---|---|---|
| 默认 | export default function Button() {} | import Button from './Button.js'; |
| 具名 | export function Button() {} | import { Button } from './Button.js'; |
// 默认导出 (Default Export)
export default function MyComponent() { }
// 具名导出 (Named Export)
export function MyComponent() { }
核心区别
当使用默认导入时,你可以在 import 语句后面进行任意命名。比如 import Banana from './Button.js',如此你能获得与默认导出一致的内容。相反,对于具名导入,导入和导出的名字必须一致。这也是称其为 具名 导入的原因!
| 特性 | 默认导出 | 具名导出 |
|---|---|---|
| 导入名称 | 可任意命名 | 必须对应导出名称 |
| IDE自动导入 | 较差,可能重名 | 优秀,精准匹配 |
| 重构支持 | 弱,无法全局重命名 | 强,支持全局重命名 |
| Tree Shaking | 可能失效 | 始终有效 |
| 代码提示 | 有限 | 完整 |
| 可读性 | 追踪来源困难 | 来源清晰明确 |
默认导出的问题 ⚠️
1. 命名混乱
// Button.js
export default function Button() {}
// 在其他文件中
import Btn from './Button'; // 合法但语义不清
import ButtonComponent from './Button'; // 另一个名字
2. 重构困难
当修改文件名或组件名时,IDE无法自动更新所有导入点。
3. Tree Shaking风险
// 默认导出对象时
export default { Button, Input, Select };
import { Button } from './components'; // 可能打包整个对象
4. 难以聚合导出
// 需要额外步骤
export { default as Button } from './Button';
具名导出的优势 ✅
1. 强类型支持
// 组件定义
export function UserCard(props: UserCardProps) {}
// 使用时自动提示所有导出
import { UserCard } from './components'; // IDE精确提示
2. 可靠的重构
// 重命名组件时,IDE可全局更新所有导入点
3. 清晰的依赖关系
import { UserCard, UserAvatar, UserMenu } from './user';
// 一目了然使用了哪些组件
4. 便于 Barrel exports
// components/index.js
export { UserCard } from './UserCard';
export { UserAvatar } from './UserAvatar';
// 使用
import { UserCard, UserAvatar } from './components';
社区推荐规范
Airbnb规范(ESLint规则)
// ❌ 不推荐
export default class MyComponent extends React.Component {}
// ✅ 推荐
export class MyComponent extends React.Component {}
ESLint配置:
{
"rules": {
"import/prefer-default-export": "off",
"import/no-default-export": "error"
}
}
React核心团队实践 React官方项目(如React DevTools)100%使用具名导出。
例外情况
默认导出在极少数场景仍可接受:
- Next.js页面(框架强制要求)
- 单一入口的库(如
export default axios) - 遗留代码兼容性
但即使在这些场景,也建议在文件内部优先使用具名导出。
总结
| 场景 | 推荐方式 | 理由 |
|---|---|---|
| React组件 | 具名导出 | 重构、可读性、Tree Shaking |
| 工具函数 | 具名导出 | 按需引入、IDE支持 |
| TypeScript类型 | 具名导出 | 必须具名 |
| 第三方库入口 | 可默认导出 | 简化使用 |
| Next.js页面 | 被迫默认 | 框架限制 |
核心原则:具名导出是React现代开发的标配,默认导出应视为例外而非常规。它带来的可维护性收益远超微小的书写便捷性。
感谢大家收看!Forever React!