# 组件设计文档
## 1. 组件分类
### 1.1 按功能分类
#### 布局组件 (components/Layout/)
- **Layout.jsx**: 主布局容器
- **Header.jsx**: 顶部导航栏
- **Sidebar.jsx**: 侧边栏菜单
#### 通用组件 (components/Common/)
- **Button.jsx**: 按钮组件
- **Input.jsx**: 输入框组件
- **Select.jsx**: 下拉选择框组件
- **DatePicker.jsx**: 日期选择器组件
- **Table.jsx**: 表格组件
- **Modal.jsx**: 弹窗组件
- **Form.jsx**: 表单组件
- **Card.jsx**: 卡片组件
- **Tag.jsx**: 标签组件
- **Badge.jsx**: 徽章组件
- **Tooltip.jsx**: 提示框组件
#### 业务组件 (components/Business/)
- **ProjectCard.jsx**: 项目卡片
- **StatCard.jsx**: 统计卡片
- **UserAvatar.jsx**: 用户头像
- **ProgressBar.jsx**: 进度条
- **StatusTag.jsx**: 状态标签
- **AmountDisplay.jsx**: 金额显示
- **DateRangePicker.jsx**: 日期范围选择器
## 2. 组件设计规范
### 2.1 Props命名规范
#### 2.1.1 布尔类型
- 使用 `is` 或 `has` 前缀
- 示例: `isLoading`, `hasPermission`, `isVisible`, `isRequired`
#### 2.1.2 事件处理
- 使用 `on` 前缀
- 示例: `onClick`, `onChange`, `onSubmit`, `onCancel`
#### 2.1.3 渲染内容
- 使用 `render` 前缀或作为 `children`
- 示例: `renderHeader`, `renderFooter`, `children`
### 2.2 组件Props定义模板
```jsx
import React from 'react';
import PropTypes from 'prop-types';
/**
* 按钮组件
* @param {string} type - 按钮类型:primary/default/danger
* @param {boolean} loading - 是否加载中
* @param {boolean} disabled - 是否禁用
* @param {function} onClick - 点击事件
* @param {node} children - 子元素
*/
const Button = ({
type = 'default',
loading = false,
disabled = false,
onClick,
children,
className,
...rest
}) => {
return (
);
};
Button.propTypes = {
type: PropTypes.oneOf(['primary', 'default', 'danger']),
loading: PropTypes.bool,
disabled: PropTypes.bool,
onClick: PropTypes.func,
children: PropTypes.node,
className: PropTypes.string,
};
export default Button;
```
## 3. 核心组件设计
### 3.1 Button(按钮组件)
```jsx
/**
* 按钮组件
*/
const Button = ({
type = 'default',
size = 'medium',
icon,
loading = false,
disabled = false,
block = false,
ghost = false,
danger = false,
onClick,
children,
...props
}) => {
const handleClick = (e) => {
if (!loading && !disabled && onClick) {
onClick(e);
}
};
return (
);
};
```
**Props说明:**
- `type`: 按钮类型 (default/primary/danger)
- `size`: 按钮大小 (small/medium/large)
- `icon`: 图标
- `loading`: 加载状态
- `disabled`: 禁用状态
- `block`: 块级按钮
- `ghost`: 幽灵按钮
- `danger`: 危险按钮
### 3.2 Table(表格组件)
```jsx
/**
* 表格组件
*/
const Table = ({
columns,
dataSource,
loading = false,
pagination,
rowKey = 'id',
rowSelection,
onRow,
scroll,
...props
}) => {
return (
);
};
```
**Props说明:**
- `columns`: 列配置
- `dataSource`: 数据源
- `loading`: 加载状态
- `pagination`: 分页配置
- `rowKey`: 行key
- `rowSelection`: 行选择配置
- `scroll`: 滚动配置
### 3.3 Form(表单组件)
```jsx
/**
* 表单组件
*/
const Form = ({
form,
initialValues,
onFinish,
onFinishFailed,
layout = 'vertical',
children,
...props
}) => {
const [formInstance] = Form.useForm();
const currentForm = form || formInstance;
return (
{children}
);
};
```
### 3.4 Modal(弹窗组件)
```jsx
/**
* 弹窗组件
*/
const Modal = ({
visible,
title,
onOk,
onCancel,
okText = '确定',
cancelText = '取消',
confirmLoading = false,
width = 520,
children,
...props
}) => {
return (
{children}
);
};
```
### 3.5 Card(卡片组件)
```jsx
/**
* 卡片组件
*/
const Card = ({
title,
extra,
bordered = true,
hoverable = false,
loading = false,
children,
className,
...props
}) => {
return (
{children}
);
};
```
### 3.6 Tag(标签组件)
```jsx
/**
* 标签组件
*/
const Tag = ({ type = 'default', color, children, ...props }) => {
const colorMap = {
new: 'blue',
inProgress: 'green',
completed: 'default',
paused: 'orange',
cancelled: 'red',
admin: 'red',
market: 'blue',
other: 'cyan',
};
return (
{children}
);
};
```
## 4. 业务组件设计
### 4.1 ProjectCard(项目卡片)
```jsx
/**
* 项目卡片组件
*/
const ProjectCard = ({
project,
onView,
onEdit,
onDelete,
showActions = true,
}) => {
const { hasRole } = usePermission();
return (
{project.name}
{project.engineering_type}
}
extra={
{project.project_no}
}
className="project-card"
>
项目负责人:
{project.project_leader}
签订日期:
{project.signing_date}
{showActions && (
{hasRole(['admin']) || project.created_by === getCurrentUserId() ? (
<>
>
) : null}
)}
);
};
```
### 4.2 StatCard(统计卡片)
```jsx
/**
* 统计卡片组件
*/
const StatCard = ({ title, value, icon, color, prefix, suffix }) => {
return (
{title}
{prefix && {prefix}}
{typeof value === 'number' ? value.toLocaleString() : value}
{suffix && {suffix}}
{icon && (
)}
);
};
```
**Props说明:**
- `title`: 标题
- `value`: 数值
- `icon`: 图标
- `color`: 颜色 (blue/green/orange/red/cyan)
- `prefix`: 前缀(如¥)
- `suffix`: 后缀(如%)
### 4.3 StatusTag(状态标签)
```jsx
/**
* 状态标签组件
*/
const StatusTag = ({ status, type = 'project' }) => {
const statusMap = {
project: {
new: { text: '新建', color: 'blue' },
inProgress: { text: '进行中', color: 'green' },
completed: { text: '已完成', color: 'default' },
paused: { text: '已暂停', color: 'orange' },
cancelled: { text: '已取消', color: 'red' },
},
user: {
active: { text: '正常', color: 'green' },
inactive: { text: '禁用', color: 'default' },
},
};
const statusInfo = statusMap[type]?.[status] || { text: status, color: 'default' };
return {statusInfo.text};
};
```
### 4.4 AmountDisplay(金额显示)
```jsx
/**
* 金额显示组件
*/
const AmountDisplay = ({ value, unit = '万元', precision = 2 }) => {
const formatAmount = (val) => {
if (val === null || val === undefined) return '-';
return val.toFixed(precision);
};
return (
{formatAmount(value)} {unit}
);
};
```
### 4.5 ProgressBar(进度条)
```jsx
/**
* 进度条组件
*/
const ProgressBar = ({ percent, status = 'active', showText = true }) => {
return (
);
};
```
### 4.6 DateRangePicker(日期范围选择器)
```jsx
/**
* 日期范围选择器组件
*/
const DateRangePicker = ({ value, onChange, placeholder }) => {
const { RangePicker } = DatePicker;
return (
);
};
```
## 5. 高阶组件
### 5.1 withAuth(认证高阶组件)
```jsx
/**
* 认证高阶组件
*/
const withAuth = (WrappedComponent, requiredRoles = []) => {
return (props) => {
const { user, isAuthenticated } = useAuth();
if (!isAuthenticated) {
return ;
}
if (requiredRoles.length > 0 && !requiredRoles.includes(user?.role)) {
return ;
}
return ;
};
};
```
### 5.2 withLoading(加载状态高阶组件)
```jsx
/**
* 加载状态高阶组件
*/
const withLoading = (WrappedComponent) => {
return ({ loading, ...props }) => {
if (loading) {
return ;
}
return ;
};
};
```
## 6. 组件复用策略
### 6.1 通过Props自定义
- 提供灵活的Props接口
- 支持自定义样式和类名
- 支持自定义渲染内容
### 6.2 通过插槽模式
- 使用 `children` 传递内容
- 使用 `render` 属性传递渲染函数
### 6.3 通过组合模式
- 将复杂组件拆分为多个小组件
- 通过组合实现复杂功能
## 7. 组件性能优化
### 7.1 React.memo
```jsx
const MemoComponent = React.memo(({ data }) => {
return {data}
;
});
```
### 7.2 useMemo
```jsx
const expensiveValue = useMemo(() => {
return computeExpensiveValue(a, b);
}, [a, b]);
```
### 7.3 useCallback
```jsx
const handleClick = useCallback(() => {
doSomething(a, b);
}, [a, b]);
```
### 7.4 虚拟滚动
对于大数据量的列表,使用虚拟滚动:
```jsx
import { List } from 'react-virtualized';
(
{data[index]}
)}
/>
```
## 8. 组件测试
### 8.1 单元测试示例
```jsx
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';
describe('Button Component', () => {
test('renders button with children', () => {
render();
expect(screen.getByText('Click me')).toBeInTheDocument();
});
test('calls onClick when clicked', () => {
const handleClick = jest.fn();
render();
fireEvent.click(screen.getByText('Click'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
test('shows loading state', () => {
render();
expect(screen.getByText('Click')).toBeDisabled();
});
});
```
## 9. 组件文档
### 9.1 Storybook(可选)
使用Storybook进行组件文档和展示:
```jsx
// stories/Button.stories.jsx
import Button from '../components/Common/Button';
export default {
title: 'Components/Button',
component: Button,
};
const Template = (args) => ;
export const Primary = Template.bind({});
Primary.args = {
type: 'primary',
children: 'Primary Button',
};
export const Secondary = Template.bind({});
Secondary.args = {
type: 'default',
children: 'Default Button',
};
```
## 10. 组件最佳实践
### 10.1 避免过度抽象
- 不要为了复用而过度抽象
- 保持组件的简单和直观
### 10.2 合理拆分组件
- 单一职责原则
- 组件不应过大(建议不超过300行)
### 10.3 Props类型检查
- 使用PropTypes进行类型检查
- 提供默认值
### 10.4 错误边界
```jsx
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error('Error:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return Something went wrong.
;
}
return this.props.children;
}
}
```
---
**文档维护**: 前端程序员
**文档类型**: 组件设计文档
**最后更新**: 2026-01-25