3.4.2 复制粘贴就能用的组件——shadcn/ui
一句话破题
shadcn/ui 不是 npm 包,而是可复制到项目中的高质量组件代码,你拥有完全控制权。
核心价值
传统组件库(如 Ant Design、MUI)是黑盒——你用它们的组件,按它们的规则定制。shadcn/ui 不同:组件代码直接复制到你的项目中,你可以随意修改。
shadcn/ui vs 传统组件库
| 特性 | shadcn/ui | 传统组件库 |
|---|---|---|
| 安装方式 | 复制代码到项目 | npm install |
| 定制性 | 完全可控 | 受限于 API |
| 更新方式 | 手动更新 | npm update |
| 体积 | 只包含使用的 | 可能引入多余代码 |
| 学习成本 | 低(标准 React) | 需学习特定 API |
快速开始
1. 初始化
bash
npx shadcn@latest init选择配置:
- Style: Default
- Base color: Slate
- CSS variables: Yes
2. 添加组件
bash
# 添加单个组件
npx shadcn@latest add button
# 添加多个组件
npx shadcn@latest add card input label
# 查看所有可用组件
npx shadcn@latest add3. 使用组件
tsx
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
export function LoginForm() {
return (
<Card className="w-[400px]">
<CardHeader>
<CardTitle>登录</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<Input placeholder="邮箱" type="email" />
<Input placeholder="密码" type="password" />
<Button className="w-full">登录</Button>
</CardContent>
</Card>
)
}常用组件速览
| 组件 | 用途 | 安装命令 |
|---|---|---|
Button | 按钮 | add button |
Input | 输入框 | add input |
Card | 卡片容器 | add card |
Dialog | 弹窗 | add dialog |
Select | 下拉选择 | add select |
Table | 表格 | add table |
Form | 表单(含验证) | add form |
Toast | 提示消息 | add toast |
组件变体
shadcn/ui 组件通常提供多种变体:
tsx
// Button 变体
<Button variant="default">默认</Button>
<Button variant="secondary">次要</Button>
<Button variant="outline">描边</Button>
<Button variant="ghost">幽灵</Button>
<Button variant="destructive">危险</Button>
// 尺寸
<Button size="sm">小</Button>
<Button size="default">中</Button>
<Button size="lg">大</Button>定制组件
组件代码在 components/ui/ 目录下,可直接修改:
tsx
// components/ui/button.tsx
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium...",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
// 添加自定义变体
brand: "bg-brand-500 text-white hover:bg-brand-600",
},
// ...
},
}
)cn() 工具函数
shadcn/ui 使用 cn() 合并类名:
tsx
import { cn } from "@/lib/utils"
// 合并默认类和自定义类
<Button className={cn("w-full", isLoading && "opacity-50")}>
提交
</Button>表单集成
shadcn/ui 的 Form 组件与 react-hook-form 深度集成:
bash
npx shadcn@latest add formtsx
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
const formSchema = z.object({
email: z.string().email("请输入有效的邮箱"),
password: z.string().min(6, "密码至少6位"),
})
export function LoginForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
})
function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values)
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>邮箱</FormLabel>
<FormControl>
<Input placeholder="your@email.com" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">登录</Button>
</form>
</Form>
)
}AI 协作指南
核心意图:让 AI 使用 shadcn/ui 组件构建 UI。
需求定义公式:
- 功能描述:我需要一个 [功能] 界面
- 组件要求:使用 shadcn/ui 的 [组件列表]
- 样式要求:[额外的 Tailwind 类]
关键术语:shadcn/ui、variant、cn()、Form、react-hook-form
交互策略:
- 先确认需要哪些 shadcn 组件
- 让 AI 生成使用这些组件的代码
- 如需表单验证,指定使用 Form + zod
避坑指南
- 先安装再使用:组件不会自动安装,需要手动
add - 路径别名:确保
@/components/ui路径正确配置 - 依赖关系:某些组件依赖其他组件,会自动一起安装
- 暗色模式:需要在
layout.tsx中配置 ThemeProvider
验收清单
- [ ] 组件正确安装到
components/ui/ - [ ] 导入路径使用
@/components/ui/xxx - [ ] 使用
cn()合并额外的类名 - [ ] 表单使用 Form 组件并配置验证
