shadcn/ui 的 Base 与 Radix 两套组件 API 差异实战:render、items 与 defaultValue 的正确写法

发布时间:2026/10/29 6:24:18

shadcn/ui 的 Base 与 Radix 两套组件 API 差异实战:render、items 与 defaultValue 的正确写法 shadcn/ui 的 Base 与 Radix 两套组件 API 差异实战render、items 与 defaultValue 的正确写法【免费下载链接】uiA set of beautifully-designed, accessible components and a code distribution platform. Works with your favorite frameworks. Open Source. Open Code.项目地址: https://gitcode.com/GitHub_Trending/ui/uishadcn/ui 仓库在组件注册表中同时维护了基于 Base UIbase与基于 Radix UIradix的两套并行组件实现两者的组合方式asChildvsrender、Select 的数据驱动模型、以及defaultValue的值类型均存在系统性差异。本文以仓库中的 base-vs-radix 规则文档 为主体完整覆盖其全部差异点与正误代码对照并结合 CLI 源码与注册表目录结构说明如何确认当前项目属于哪一套 API从而避免在迁移或跨项目复用组件代码时写出编译不通过或行为不符预期的 JSX。先确认你的项目用的是哪一套npx shadcn info的base字段规则文档的开篇要求先运行npx shadcnlatest info查看输出中的base字段再决定按哪一套 API 编写代码。该字段由 CLI 的 info 命令 生成// packages/shadcn/src/commands/info.ts const config await getConfig(cwd) const base getBase(config?.style)而base的取值逻辑实现在 getBase 函数// packages/shadcn/src/utils/get-config.ts export function getBase(style: string | undefined): PresetBase { // An undefined style means no existing config, so default to base. // Any defined style, including empty and unprefixed legacy values // (new-york, new-york-v4, default), stays radix. if (style undefined) { return base } return parsePresetStyle(style).base ?? radix }从源码结构看可以得出两条实用结论没有components.json配置全新项目时默认归入base任何已定义的 style包括new-york、new-york-v4等遗留值都会停留在radix。也就是说base/radix不是两个可自由混搭的组件库而是同一项目必须整体选定的两套 API。仓库中这两套实现分别位于 apps/v4/registry/bases/base 与 apps/v4/registry/bases/radix 两个并行目录注册表 README 明确要求对任何共享表面同样的预览块、同样的示例意图变更应同时应用到两套变体只调整必须不同的部分——导入路径.../base/ui/...与.../radix/ui/...和原语 API。这正解释了为什么本文列出的每一条差异都必须“成对记忆”同名的DialogTrigger、Select、Accordion在两个目录下的 props 签名并不相同。组合方式radix 用asChildbase 用render两套 API 最基础、也最普遍的区别在于“替换默认元素”的组合机制Radix 使用asChild把默认元素替换为子元素Base 使用renderprop 声明渲染成什么元素。无论哪一套都不要用多余的包裹元素套住 trigger。错误写法两种体系都错DialogTrigger div ButtonOpen/Button /div /DialogTrigger正确写法radixDialogTrigger asChild ButtonOpen/Button /DialogTrigger正确写法baseDialogTrigger render{Button /}Open/DialogTrigger注意两者子内容的语义差异radix 的asChild是“用唯一子元素替换自身”子元素即触发按钮base 的render是“把自身渲染为指定元素”触发文案作为 children 传入。这个差异在 base 注册表的组件源码中随处可见例如 alert-dialog.tsxAlertDialogPrimitive.Cancel >Button render{a href/docs /}Read the docs/Button正确baseButton render{a href/docs /} nativeButton{false} Read the docs /Button等价写法radixButton asChild a href/docsRead the docs/a /Button同样的规则适用于render不是Button的 trigger 组件// base. PopoverTrigger render{InputGroupAddon /} nativeButton{false} Pick date /PopoverTrigger判断口诀只要渲染目标是a、span这类非button元素base 体系就补一个nativeButton{false}radix 体系没有这个 prop用asChild即可。Select 差异items prop、placeholder 与定位Select 是两套 API 差异最大的组件之一共有四个差异点。items propbase 必须在根节点声明base 体系要求根Select携带items数组数据驱动radix 体系只使用内联 JSX。错误base——缺少itemsSelect SelectTriggerSelectValue placeholderSelect a fruit //SelectTrigger /Select正确baseconst items [ { label: Select a fruit, value: null }, { label: Apple, value: apple }, { label: Banana, value: banana }, ] Select items{items} SelectTrigger SelectValue / /SelectTrigger SelectContent SelectGroup {items.map((item) ( SelectItem key{item.value} value{item.value}{item.label}/SelectItem ))} /SelectGroup /SelectContent /Select正确radix——纯内联 JSXSelect SelectTrigger SelectValue placeholderSelect a fruit / /SelectTrigger SelectContent SelectGroup SelectItem valueappleApple/SelectItem SelectItem valuebananaBanana/SelectItem /SelectGroup /SelectContent /Selectplaceholderbase 用value: null项radix 用placeholderpropbase在items数组里放一个{ label: ..., value: null }项SelectValue /不再需要placeholderradixSelectValue placeholderSelect a fruit /。迁移时的典型错误就是把 radix 的placeholder...原样带到 base 版本结果占位文案不显示——base 的占位是数据不是 prop。内容定位alignItemWithTriggervsposition两套体系对浮层定位的 prop 命名不同// base. SelectContent alignItemWithTrigger{false} sidebottom // radix. SelectContent positionpopperbasealignItemWithTrigger{false}表示列表不强制与选中项对齐radixpositionpopper表示用 popper 定位相对触发器否则为item-aligned。Select 多选与对象值base 独有base 体系支持multiple、SelectValue的渲染函数 children以及配合itemToStringValue的对象值radix 体系的Select只支持单选且值只能是字符串。这两组能力在跨体系迁移时没有对等物需要改用Combobox等其他组件替代radix 侧多选通常由 Combobox 承担。base——多选Select items{items} multiple defaultValue{[]} SelectTrigger SelectValue {(value: string[]) value.length 0 ? Select fruits : ${value.length} selected} /SelectValue /SelectTrigger ... /Selectbase——对象值Select defaultValue{plans[0]} itemToStringValue{(plan) plan.name} SelectTrigger SelectValue{(value) value.name}/SelectValue /SelectTrigger ... /Select两个要点itemToStringValue负责把对象值序列化为字符串用于内部状态与无障碍播报SelectValue的 children 作为渲染函数接收当前值可渲染对象上的任意字段。radix 体系两者皆无遇到对象值场景不要硬套Select。ToggleGroupradix 用typebase 用multiple布尔值单选/多选的开关在两套体系中表达方式不同且base 的defaultValue永远是数组radix 单选时是字符串。错误base——误用 radix 的typepropToggleGroup typesingle defaultValuedaily ToggleGroupItem valuedailyDaily/ToggleGroupItem /ToggleGroup正确base// Single (no prop needed), defaultValue is always an array. ToggleGroup defaultValue{[daily]} spacing{2} ToggleGroupItem valuedailyDaily/ToggleGroupItem ToggleGroupItem valueweeklyWeekly/ToggleGroupItem /ToggleGroup // Multi-selection. ToggleGroup multiple ToggleGroupItem valueboldBold/ToggleGroupItem ToggleGroupItem valueitalicItalic/ToggleGroupItem /ToggleGroup正确radix// Single, defaultValue is a string. ToggleGroup typesingle defaultValuedaily spacing{2} ToggleGroupItem valuedailyDaily/ToggleGroupItem ToggleGroupItem valueweeklyWeekly/ToggleGroupItem /ToggleGroup // Multi-selection. ToggleGroup typemultiple ToggleGroupItem valueboldBold/ToggleGroupItem ToggleGroupItem valueitalicItalic/ToggleGroupItem /ToggleGroup对照总结能力baseradix单选默认无需 proptypesingle多选multipletypemultipledefaultValue类型恒为数组[daily]单选为字符串daily受控单选值的差异最能体现“base 一切皆数组”的设计// base — wrap/unwrap arrays. const [value, setValue] React.useState(normal) ToggleGroup value{[value]} onValueChange{(v) setValue(v[0])} // radix — plain string. const [value, setValue] React.useState(normal) ToggleGroup typesingle value{value} onValueChange{setValue}base 侧需要在边界处做“数组包装 / 拆包”value{[value]}进、v[0]出radix 侧直接透传字符串。迁移受控组件时漏掉这层包装是典型故障点。Sliderbase 单滑块可传标量radix 恒为数组Base 对单滑块接受普通数字Radix 一律要求数组因为 Radix Slider 原生就是多滑块模型。错误base——给单滑块传数组Slider defaultValue{[50]} max{100} step{1} /正确baseSlider defaultValue{50} max{100} step{1} /正确radixSlider defaultValue{[50]} max{100} step{1} /范围滑块range slider两边都用数组。受控的onValueChange在 base 下可能需要类型断言// base. const [value, setValue] React.useState([0.3, 0.7]) Slider value{value} onValueChange{(v) setValue(v as number[])} / // radix. const [value, setValue] React.useState([0.3, 0.7]) Slider value{value} onValueChange{setValue} /base 中onValueChange的回调参数类型同时覆盖标量与数组两种形态因此范围滑块场景需要v as number[]断言后写入 state。Accordiontype/collapsibleradixvsmultiplebaseRadix 要求显式typesingle或typemultiple并支持collapsible允许收起已展开项defaultValue是字符串。Base 没有typeprop用multiple布尔值控制多选defaultValue永远是数组。错误base——照搬 radix 的写法Accordion typesingle collapsible defaultValueitem-1 AccordionItem valueitem-1.../AccordionItem /Accordion正确baseAccordion defaultValue{[item-1]} AccordionItem valueitem-1.../AccordionItem /Accordion // Multi-select. Accordion multiple defaultValue{[item-1, item-2]} AccordionItem valueitem-1.../AccordionItem AccordionItem valueitem-2.../AccordionItem /Accordion正确radixAccordion typesingle collapsible defaultValueitem-1 AccordionItem valueitem-1.../AccordionItem /Accordion迁移与双目录维护仓库给出的工程化支撑上述逐组件差异之所以值得沉淀成规则文档是因为仓库中存在大量从 radix 到 base 的存量迁移与并行维护工作。两点工程化事实可以作为佐证并行注册表结构apps/v4/registry/bases 目录下base/与radix/两套组件一一对应如 base/ui/accordion.tsx 与 radix 侧同名文件bases README 要求共享表面的变更同时落到两边仅调整导入路径与原语 API。迁移技能与映射表仓库自带 migrate-radix-to-base 技能并按组件类别拆分了 menus.md、overlays.md、form-controls.md 等映射文档与 shadcn 技能规则目录 互为配套CLI 侧也提供 migrate 命令 供项目执行迁移。对开发者而言日常只需记住规则文档的判定路径先看info输出的base字段确定体系再按对应一侧的写法实现组件跨项目复制粘贴代码时把asChild/render、type/multiple、字符串 / 数组defaultValue、placeholder/value: null这四组差异当成必查清单。速查表场景baseBase UIradixRadix UI元素替换render{Button /}asChild 子元素渲染为非 button 元素追加nativeButton{false}无需额外 propSelect 选项根节点items数组内联SelectItemJSXSelect 占位{ label, value: null }项SelectValue placeholder... /Select 定位alignItemWithTriggerpositionpopperSelect 多选 / 对象值multiple、itemToStringValue、渲染函数 children不支持仅单选字符串值ToggleGroup 多选multipletypemultipleToggleGroup 单选默认typesingleToggleGroupdefaultValue恒为数组单选为字符串Slider 单滑块值标量50数组[50]Accordion 类型无typemultiple布尔typesingle \| multiple支持collapsibleAccordiondefaultValue恒为数组单选为字符串参考依据规则文档 base-vs-radix.md、info 命令实现、getBase 取值逻辑、注册表并行结构说明 以及 base 侧组件源码如 alert-dialog.tsx 的render用法。【免费下载链接】uiA set of beautifully-designed, accessible components and a code distribution platform. Works with your favorite frameworks. Open Source. Open Code.项目地址: https://gitcode.com/GitHub_Trending/ui/ui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/24 14:47:52

AI辅助开发A股量化工具:回测校验与实战防坑指南

前两天有人私信我,说想用AI直接给推几只明天能涨的股票。我回了一句:这个方向从起跑线就歪了。大模型并不适合用来猜行情,它真正擅长的是帮我把“量化工具”这种工程强度很高的东西快速落地。我自己最近就在用AI开发一个A股量化研究工具&…

2026/10/30 2:35:55

班车投诉率降 15%:问题多半不在车,在流程

班车投诉率降 15%:问题多半不在车,在流程 “在你们来之前,我本来准备了一大堆问题刁难你们的,现在没有任何问题了,非常好。” 这句话是万翼科技(万科全资子公司)的行政助理曹婷说的。她在班车供…

2026/10/30 2:35:55

C 盘满了先别清缓存:同一块硬盘上的空闲空间怎么借给系统盘

Windows 上 C 盘满了,很多人第一反应是清缓存、删文件、搬家。其实只要 C 盘和 D 盘在同一块物理硬盘上,D 盘空着的那些空间是可以直接"借"给 C 盘的——不需要重装系统,不需要格式化,也不需要把文件搬来搬去。 本文按实…

2026/10/30 2:35:55

汽车电子电性能测试

现代汽车正加速“电子化”“智能化”——ECU、传感器、执行器、车载信息娱乐、车灯与仪表等电子电气设备,都要靠车载电源供电。然而车载供电系统并非“稳定如一”:发动机起动瞬间电压跌落、电池老化与负载投切带来的电压波动、线束接触不良引发的瞬时中断…

2026/10/30 2:35:55

微信小程序变脸游戏

前言本次课程案例是利用小程序加速度传感器 wx.onAccelerometerChange 制作变脸小游戏。功能包含点击图片随机切换脸谱、摇晃手机自动变脸&#xff0c;同时完成作业扩展&#xff1a;统计并展示累计变脸次数。开发过程遇到了 Skyline 渲染器 <navigation-bar> 导航栏组件报…

2026/10/29 17:05:52

全国计算机二级C语言真题PDF高效刷题指南

简介&#xff1a;这份PDF是全国计算机二级C语言考试的试题与答案解析&#xff0c;专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/29 17:06:02

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介&#xff1a;一份以实战为导向的Python爬虫入门资源&#xff0c;面向具备基本编程基础、希望快速掌握网络数据抓取的初学者&#xff0c;可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档&#xff0c;完整演示从网页中提取 标题…

2026/10/29 17:06:13

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介&#xff1a;这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档&#xff0c;压缩包大小七十八KB&#xff0c;内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开&#xff1a;先构造一个极点位于单位圆内…

2026/10/30 0:00:46

NCP1342高频准谐振反激控制器:从设计约束到验收的完整方案

简介&#xff1a;NCP1342 高频准谐振反激控制器应用介绍译文文档&#xff0c;面向电源设计工程师、硬件研发人员及开关电源学习者&#xff0c;帮助读者跨越英文原版资料的语言门槛&#xff0c;系统理解这款高集成度 QR Flyback 控制器的设计要点。文档围绕芯片核心特性展开&…

2026/10/30 0:00:46

NCP1342准谐振反激电源设计:从选型到验收的全流程解析

简介&#xff1a;这份文档面向电源设计工程师与开关电源学习者&#xff0c;系统梳理NCP1342高频准谐振反激控制器的应用要点&#xff0c;帮助读者快速理解这款高集成度离线电源变换器控制芯片的工作机制与设计方法。内容涵盖芯片核心特性、引脚功能定义、电气特性参数表、最大额…

2026/10/30 0:00:46

Web系统自动登出机制设计与实现全解析

1. 系统自动登出机制的设计初衷在各类Web应用和后台管理系统中&#xff0c;自动登出功能早已成为标配。这个看似简单的功能背后&#xff0c;实际上涉及用户安全、资源管理和体验优化的多重考量。作为从业十多年的老开发&#xff0c;我见过太多因为登出逻辑设计不当导致的安全事…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑