基础UI组件
|
全文共计 1037 字
|
预计阅读 5 分钟
基础UI组件
基础UI组件是项目UI系统的核心构建块,基于 Radix UI 和 Shadcn/ui 构建,提供了一套可访问、可定制且一致的UI元素。
组件列表
1. Button (按钮)
按钮组件用于触发操作。
基本用法
import { Button } from '@/components/ui/button';
<Button variant="primary" size="md" onClick={handleClick}>
点击我
</Button>
Props说明
属性名 | 类型 | 默认值 | 描述 |
---|---|---|---|
variant | 'primary' | 'secondary' | 'ghost' |
size | 'sm' | 'md' | 'lg' |
disabled | boolean | false | 是否禁用 |
onClick | Function | - | 点击事件处理函数 |
children | React.ReactNode | - | 按钮内容 |
样式变体
- primary: 主要操作按钮,使用品牌色
- secondary: 次要操作按钮,使用次要色
- ghost: 幽灵按钮,透明背景,悬停时显示背景
尺寸变体
- sm: 小尺寸按钮
- md: 中等尺寸按钮
- lg: 大尺寸按钮
2. Card (卡片)
卡片组件用于展示内容区块。
基本用法
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@/components/ui/card';
<Card>
<CardHeader>
<CardTitle>卡片标题</CardTitle>
<CardDescription>卡片描述</CardDescription>
</CardHeader>
<CardContent>
<p>卡片内容</p>
</CardContent>
<CardFooter>
<Button>操作按钮</Button>
</CardFooter>
</Card>
组件结构
- Card: 卡片容器
- CardHeader: 卡片头部,包含标题和描述
- CardTitle: 卡片标题
- CardDescription: 卡片描述
- CardContent: 卡片内容区域
- CardFooter: 卡片底部操作区域
3. Input (输入框)
输入框组件用于用户输入文本。
基本用法
import { Input } from '@/components/ui/input';
<Input
type="text"
placeholder="请输入内容"
value={value}
onChange={handleChange}
/>
Props说明
属性名 | 类型 | 默认值 | 描述 |
---|---|---|---|
type | string | 'text' | 输入框类型 |
placeholder | string | - | 占位符文本 |
value | string | - | 输入框值 |
onChange | Function | - | 值变化事件处理函数 |
disabled | boolean | false | 是否禁用 |
4. Dialog (对话框)
对话框组件用于显示模态对话框。
基本用法
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
<Dialog>
<DialogTrigger asChild>
<Button>打开对话框</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>对话框标题</DialogTitle>
<DialogDescription>对话框描述</DialogDescription>
</DialogHeader>
<div>对话框内容</div>
<DialogFooter>
<Button>确认</Button>
</DialogFooter>
</DialogContent>
</Dialog>
组件结构
- Dialog: 对话框容器
- DialogTrigger: 对话框触发器
- DialogContent: 对话框内容区域
- DialogHeader: 对话框头部
- DialogTitle: 对话框标题
- DialogDescription: 对话框描述
- DialogFooter: 对话框底部操作区域
5. DropdownMenu (下拉菜单)
下拉菜单组件用于显示一组操作选项。
基本用法
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator } from '@/components/ui/dropdown-menu';
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost">打开菜单</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>菜单标题</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem>选项1</DropdownMenuItem>
<DropdownMenuItem>选项2</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
组件结构
- DropdownMenu: 下拉菜单容器
- DropdownMenuTrigger: 菜单触发器
- DropdownMenuContent: 菜单内容区域
- DropdownMenuLabel: 菜单标签
- DropdownMenuSeparator: 菜单分隔线
- DropdownMenuItem: 菜单项
6. Alert (警告)
警告组件用于显示重要信息。
基本用法
import { Alert, AlertTitle, AlertDescription } from '@/components/ui/alert';
<Alert variant="default">
<AlertTitle>提示</AlertTitle>
<AlertDescription>这是一条重要信息</AlertDescription>
</Alert>
Props说明
属性名 | 类型 | 默认值 | 描述 |
---|---|---|---|
variant | 'default' | 'destructive' | 'default' |
样式变体
- default: 默认警告样式
- destructive: 危险警告样式
设计规范
1. 可访问性
所有基础UI组件都遵循以下可访问性原则:
- 支持键盘导航
- 提供适当的ARIA标签
- 确保足够的颜色对比度
- 支持屏幕阅读器
2. 响应式设计
组件在不同屏幕尺寸下都能良好显示:
- 移动端适配
- 平板端适配
- 桌面端适配
- 触摸设备优化
3. 一致性
- 统一的视觉风格
- 一致的交互行为
- 标准化的动画效果
- 统一的间距和布局
自定义样式
1. 使用Tailwind CSS类名
可以通过传递className属性自定义组件样式:
<Button className="bg-red-500 hover:bg-red-600">
自定义样式按钮
</Button>
2. 使用CSS变量
通过CSS变量定制主题:
:root {
--primary: #3b82f6;
--secondary: #64748b;
}
3. 组件变体扩展
可以通过扩展组件的variant属性添加新的样式变体:
// 在组件定义中添加新的变体
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background",
{
variants: {
variant: {
primary: "bg-primary text-primary-foreground hover:bg-primary/90",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
// 添加新的变体
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
},
size: {
sm: "h-9 rounded-md px-3",
md: "h-10 py-2 px-4",
lg: "h-11 rounded-md px-8",
},
},
defaultVariants: {
variant: "primary",
size: "md",
},
}
);
性能优化
1. 懒加载
对于非关键组件,可以使用懒加载:
import { lazy, Suspense } from 'react';
const LazyComponent = lazy(() => import('@/components/ui/some-component'));
<Suspense fallback={<div>加载中...</div>}>
<LazyComponent />
</Suspense>
2. Memoization
使用React.memo避免不必要的重渲染:
import { memo } from 'react';
const Button = memo(({ onClick, children }: ButtonProps) => {
return (
<button onClick={onClick}>
{children}
</button>
);
});
3. 代码分割
通过动态导入实现代码分割:
// 动态导入组件
const DynamicComponent = dynamic(() => import('@/components/ui/some-component'), {
loading: () => <p>加载中...</p>
});
测试指南
1. 单元测试
使用React Testing Library进行组件测试:
import { render, screen } from '@testing-library/react';
import { Button } from '@/components/ui/button';
test('按钮应该正确渲染', () => {
render(<Button>点击我</Button>);
expect(screen.getByText('点击我')).toBeInTheDocument();
});
2. 快照测试
确保组件UI一致性:
import { render } from '@testing-library/react';
import { Button } from '@/components/ui/button';
test('按钮快照测试', () => {
const { asFragment } = render(<Button>点击我</Button>);
expect(asFragment()).toMatchSnapshot();
});
3. 交互测试
测试用户交互行为:
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from '@/components/ui/button';
test('按钮点击事件', () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>点击我</Button>);
fireEvent.click(screen.getByText('点击我'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
最佳实践
1. 组件使用
- 优先使用现有组件而非创建新组件
- 合理组合基础组件构建复杂UI
- 遵循组件的Props设计规范
- 注意组件的可访问性支持
2. 样式定制
- 使用Tailwind CSS类名而非内联样式
- 通过CSS变量定制主题色
- 避免过度定制破坏设计一致性
- 保持响应式设计适配
3. 性能优化
- 合理使用memo避免重渲染
- 懒加载非关键组件
- 优化组件Props传递
- 注意事件处理函数的优化
通过这些基础UI组件,项目能够构建出一致、可访问且高性能的用户界面。