shadcn/ui radix ui 讲解
# 一、Radix UI 是什么?一句话理解
- Radix UI = Headless(无样式)的、可访问性优先的 React 交互组件原语
它提供:
- ✅ 行为逻辑(open / close / focus)
- ✅ 键盘交互
- ✅ ARIA 属性
- ✅ 状态管理
- ❌ 不提供样式
👉 它是“交互层”,不是“UI 层”
# 二、为什么 Radix UI 很重要?
如果你自己写一个 Dialog,需要处理:
- ESC 关闭
- 焦点锁定(focus trap)
- Tab 循环
- aria-modal
- 屏幕阅读器
- Portal
👉 Radix 全帮你搞定,而且符合 WAI-ARIA 标准
# 三、Radix UI 的核心设计哲学
# 1️⃣ Headless(无样式)
<DialogContent className="bg-white rounded" /-
1
样式完全由你控制
# 2️⃣ Compound Components(组合组件)
<Dialog>
<DialogTrigger />
<DialogContent />
</Dialog>
1
2
3
4
2
3
4
- 父组件提供 context
- 子组件消费 context
- 强约束、强语义
# 3️⃣ 状态可控 / 不可控
<Dialog open={open} onOpenChange={setOpen} />
1
或者:
<Dialog defaultOpen />
1
# 4️⃣ Accessibility First(不是事后补)
Radix 的每一个 API 都围绕可访问性设计。
# 四、Radix UI 组件分类
# Overlay 类(最重要)
- Dialog
- AlertDialog
- Popover
- Tooltip
- DropdownMenu
- ContextMenu
👉 90% 的交互来自这里
# Form & Input
- Checkbox
- RadioGroup
- Switch
- Slider
- Select
# Navigation
- Tabs
- Accordion
- NavigationMenu
# 五、核心机制一:Trigger / Content
<Popover>
<PopoverTrigger>Open</PopoverTrigger>
<PopoverContent>Content</PopoverContent>
</Popover>
1
2
3
4
2
3
4
Radix 内部:
- Trigger 控制 open
- Content 响应 open
- 状态通过 context 共享
# 六、asChild(非常重要)
# 为什么要 asChild?
<DialogTrigger>
<Button />
</DialogTrigger>
1
2
3
2
3
❌ 会多包一层 DOM
# 正确方式
<DialogTrigger asChild>
<Button />
</DialogTrigger>
1
2
3
2
3
👉 不新增 DOM,只注入行为
底层用的是 Slot
# 七、Portal(解决层级问题)
<DialogPortal>
<DialogContent />
</DialogPortal>
1
2
3
2
3
- 渲染到 body
- 避免 z-index 地狱
# 八、Radix 的 State & Data Attributes
Radix 会自动注入:
data-state="open"
data-disabled
data-side="top"
1
2
3
2
3
你可以直接用 Tailwind:
className="
data-[state=open]:animate-in
data-[state=closed]:animate-out
"
1
2
3
4
2
3
4
👉 这是 shadcn/ui 动画的关键
# 九、受控 vs 非受控(一定要懂)
# 非受控(简单)
<Dialog defaultOpen />
1
# 受控(推荐在业务中)
<Dialog open={open} onOpenChange={setOpen} />
1
# 十、以 Dialog 为例(完整解构)
<Dialog>
<DialogTrigger asChild>
<Button>Open</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Title</DialogTitle>
<DialogDescription>Desc</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Radix 负责:
- open 状态
- ESC
- focus trap
- aria-describedby
shadcn/ui 负责:
- className
- 动画
- 结构封装
# 十一、常见误区
- ❌ Radix 当 UI 库用
- ❌ 在 Trigger 里写业务逻辑
- ❌ 忽略 data-state
- ❌ 不用 asChild
# 十二、Radix UI + shadcn/ui 的关系
| Radix | shadcn/ui |
|---|---|
| 交互原语 | 样式封装 |
| 无样式 | Tailwind |
| a11y | Design System |
| 行为 | 视觉 |
# 十三、你什么时候算“会 Radix UI”?
你能:
- 手写 Dialog / Popover / Tabs
- 正确使用 asChild
- 利用 data-state 写动画
- 封装而不是直接使用 Radix
上次更新: 2026/01/07, 09:20:46