目录结构规范
组件开发和目录结构规范是前端工程化的重要部分,合理的规范能提升代码可维护性和团队协作效率。从组件设计原则到目录组织方式,规范的制定需要结合实际项目需求和技术栈特点。
组件设计原则
组件应当遵循单一职责原则,每个组件只关注特定功能。例如按钮组件只处理点击交互和样式呈现,不包含业务逻辑:
// Good: 职责单一的按钮组件
const Button = ({ onClick, children }) => (
<button
className="base-btn"
onClick={onClick}
>
{children}
</button>
);
// Bad: 混杂业务逻辑的按钮
const LoginButton = () => {
const handleLogin = () => {
// 登录逻辑...
};
return (
<button onClick={handleLogin}>
登录
</button>
);
};
组件接口设计需要保持props一致性,布尔类型prop省略值时应默认为true:
<Modal visible /> // 等同于 visible={true}
组件文件结构
单个组件应包含完整的功能单元文件,典型结构如下:
components/
├── Button/
│ ├── index.tsx // 组件入口
│ ├── Button.tsx // 组件实现
│ ├── Button.less // 组件样式
│ ├── Button.test.tsx // 单元测试
│ └── README.md // 文档说明
复合组件采用扁平化结构组织:
form/
├── Form.tsx
├── FormItem.tsx
├── FormInput.tsx
└── index.ts
目录结构规范
项目根目录建议按功能划分:
project/
├── src/
│ ├── assets/ # 静态资源
│ ├── components/ # 通用组件
│ ├── hooks/ # 自定义Hook
│ ├── pages/ # 页面组件
│ ├── services/ # API服务
│ ├── stores/ # 状态管理
│ ├── utils/ # 工具函数
│ └── App.tsx
├── .storybook/ # 组件文档配置
└── public/ # 公共资源
页面级组件目录示例:
pages/
├── user/
│ ├── components/ # 页面私有组件
│ ├── hooks/ # 页面专属Hook
│ ├── UserList.tsx
│ ├── UserDetail.tsx
│ └── index.ts # 页面路由出口
命名约定
组件文件名使用PascalCase,工具函数使用camelCase:
components/
├── DatePicker.tsx
└── useWindowSize.ts
样式文件与组件同名:
Button/
├── Button.tsx
└── Button.module.css
代码组织规范
组件内部代码建议按以下顺序组织:
interface Props {
// TypeScript接口定义
}
const Component: React.FC<Props> = (props) => {
// Hook调用
const [state, setState] = useState();
// 内部函数
const handleClick = () => {};
// 渲染内容
return <div>{/* ... */}</div>;
};
样式管理方案
推荐CSS Modules或CSS-in-JS方案:
// CSS Modules示例
import styles from './Button.module.css';
const Button = () => (
<button className={styles.primary}>
按钮
</button>
);
// styled-components示例
const StyledButton = styled.button`
padding: 8px 16px;
background: ${props => props.primary ? '#1890ff' : '#fff'};
`;
测试文件规范
测试文件与组件同级存放,使用*.test.tsx
命名:
// Button.test.tsx
describe('Button Component', () => {
it('should trigger onClick', () => {
const mockFn = jest.fn();
render(<Button onClick={mockFn} />);
fireEvent.click(screen.getByRole('button'));
expect(mockFn).toBeCalledTimes(1);
});
});
文档规范
每个组件目录应包含README.md说明:
# Button 按钮
## 基本用法
```jsx
<Button type="primary">提交</Button>
```
## API
| 属性 | 说明 | 类型 | 默认值 |
|------|------|------|-------|
| type | 按钮类型 | 'primary'|'default' | 'default' |
类型定义规范
组件Props使用TypeScript接口定义:
interface ButtonProps {
/**
* 按钮尺寸
* @default 'medium'
*/
size?: 'small' | 'medium' | 'large';
/**
* 点击事件处理器
*/
onClick?: (event: React.MouseEvent) => void;
}
版本控制策略
组件库更新遵循语义化版本:
- 补丁版本(0.0.x):向后兼容的问题修正
- 次要版本(0.x.0):向后兼容的功能新增
- 主要版本(x.0.0):不兼容的API修改
多包管理方案
大型项目可采用monorepo结构:
packages/
├── components/
│ └── package.json
├── theme/
│ └── package.json
└── utils/
└── package.json
自动化工具集成
通过Plop.js生成组件模板:
// plopfile.js
module.exports = function(plop) {
plop.setGenerator('component', {
description: 'Create a new component',
prompts: [{
type: 'input',
name: 'name',
message: 'Component name(PascalCase):'
}],
actions: [{
type: 'add',
path: 'src/components/{{name}}/index.tsx',
templateFile: 'templates/component.hbs'
}]
});
};
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn