十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

shadcn Radix → Base UI 迁移中的调用点改造指南:Consumer-Side Prop 变更清单与排查流程

shadcn Radix → Base UI 迁移中的调用点改造指南:Consumer-Side Prop 变更清单与排查流程 shadcn Radix → Base UI 迁移中的调用点改造指南Consumer-Side Prop 变更清单与排查流程【免费下载链接】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本文聚焦 consumer-props.md 这份迁移参考资料在 Radix 到 Base UIbase-ui/react迁移中shadcn 组件包装器的导出名保持不变但业务代码**调用点call sites**上的 props 会发生变更或直接消失。读完本篇你将掌握一份逐组件的 props 改造清单含回调签名规则、asChild→render的通用替换模式以及一套可执行的“grep 排查 → 逐文件修复 → FLAG 行为差异”标准流程并能结合本仓库的双注册表源码验证每个映射。1. 为什么调用点需要单独一步迁移工作分为两层组件包装器components/ui下的 shadcn wrapper和业务代码wrapper 的消费者。SKILL.md 的迁移策略说明中指出包装器可以通过 CLI 的“golden pair”机制自动化交付 Base UI 变体但Consumer/app code has no CLI mechanism: always hand-migrate it againstconsumer-props.md.也就是说应用代码没有 CLI 机制只能对照本文的清单手工迁移。这正是 consumer-props.md 存在的意义它列出的是“wrapper 名不变、但调用处 props 必须改”的完整清单全部条目均经过base-ui/react1.6.0类型定义的核对文档明确给出核验原则——拿不准时去查node_modules/base-ui/react/**/*.d.ts永远不要猜。本仓库也维护着可对照验证的“地面真相”apps/v4/registry/bases 下并排存在base/Base UI 支撑与radix/Radix 支撑两套注册表universal-patterns.md声明的知识库即来自对apps/v4/registry/bases/{radix,base}/ui/中 61 组组件对的机械 diff。迁移时可以用同一组件的两套包装器源码互相印证本文表格。2. 通用规则asChild→render文档中的 Universal 一节只有一条但它是调用点改造中出现频率最高的一条RadixBase UI调用点动作asChild任意 wrapperrenderpropTrigger asChildButton//Trigger→Trigger render{Button/}...Radix 的asChild是布尔标志把 props 合并到唯一子元素上Base UI 的render直接接收要渲染的元素。本仓库 Base 变体包装器中随处可见这一模式例如 dialog.tsx 的关闭按钮DialogPrimitive.Close render{Button variantoutline /}alert-dialog.tsx 同样以render{Button variant{variant} size{size} /}取代了 Radix 时代的asChild。因此排查时对所有组件统一执行grepasChild逐个替换为render配合 universal-patterns.md 中的 Slot 手动惯用法改写规则非按钮多态组件改用useRendermergeProps如 breadcrumb.tsx 所示。3. 逐组件 props 变更清单以下表格完整继承 consumer-props.md 的 Per component 清单按组件族分组并补充仓库内可验证的实现证据。3.1 表单控件Accordion、Checkbox、Slider、Select、ToggleGroup组件Radix propBase UI 去向调用点动作Accordiontypesingle\|multiplecollapsible移除value/defaultValue永远是数组多开通过multipletypesingle collapsible→ 两者都删值包成数组typemultiple→multipleCheckboxcheckedindeterminateindeterminate是独立的布尔 propcheckedindeterminate→indeterminate 布尔checkedSlideronValueChange(value)签名获得事件详情参数另外inverted被移除检查 handler 形参个数删除inverted若有 vertical-inverted 用法需 FLAGSlideronValueCommitonValueCommitted重命名Selectpositionpopper\|item-alignedalignItemWithTrigger布尔量位于 Positioner 上wrapper 已暴露positionpopper→alignItemWithTrigger{false}item-aligned→alignItemWithTrigger默认值SelectonValueChange(value: string)加宽为(value: Value \| null, eventDetails)useStatestringonValueChange{setState}会编译失败把 state 加宽为string \| null或包一层 setterToggleGrouptypesingle\|multiplemultiple布尔量value 形状为数组与 Accordion 同样处理Accordion 的“值永远是数组”不是文字游戏本仓库的 Base 示例直接体现了这一点——accordion-basic.tsx 中写的是defaultValue{[item-1]}而 Radix 版本对应的是标量。同时注意 Base 包装器中AccordionContent实际渲染的是AccordionPrimitive.Panel见 accordion.tsx即 Radix 的Content部件在 Base 中改名为Panel但shadcn 包装器导出名仍是AccordionContent调用点不需要改名只需处理 props。Select 的onValueChange加宽是最容易在 typecheck 中爆雷的一条如果应用里写const [value, setValue] useStatestring(...)然后onValueChange{setValue}迁移后setValue不接受null直接编译失败。修法有两种——把 state 类型改为string \| null或包一层(v: string \| null) setValue(v ?? )。3.2 反馈与浮层Tooltip、Dialog 家族、Popover/HoverCard组件Radix propBase UI 去向调用点动作TooltipProviderdelayDuration、skipDelayDurationdelayskip-delay 概念被移除重命名 / 删除TooltipdisableHoverableContent无等价物删除在迁移报告中 FLAG 行为变化Popover / HoverCardRoot 上的openDelay/closeDelay移到TRIGGER上名为delay/closeDelay把 props 从 Root 搬到 TriggerDialog / AlertDialogonOpenAutoFocusinitialFocus基于元素/ref而非事件重构传目标而不是 preventDefault 回调Dialog / AlertDialogonCloseAutoFocusfinalFocus同样重构Dialog 家族onEscapeKeyDown、onPointerDownOutside、onInteractOutside已合并精确的逐部件签名见 overlays 参考查 overlays.md不要猜overlays.md 对最后一行给出了可直接落地的细节Radix 的逐交互回调onEscapeKeyDown/onPointerDownOutside/onFocusOutside/onInteractOutside在 Base UI 中没有一一对应的 prop统一由onOpenChange的第二个参数eventDetails承接——判断eventDetails.reasonescape-key、outside-press、focus-out再调用eventDetails.cancel()来阻止关闭等价于 Radix 的event.preventDefault()。而onOpenAutoFocus/onCloseAutoFocus则改到 Popup 部件的initialFocus/finalFocus接受boolean \| RefObject \| (openType) ...三种形态所以调用点从“事件处理器”变成“焦点目标”的重构。3.3 导航类Tabs、Menubar、ContextMenu、NavigationMenu、Toolbar组件Radix propBase UI 去向调用点动作TabsactivationModemanual移除Base UI 默认就是手动激活删除 prop近似替代是Tabs.List activateOnFocus行为有差异FLAG不要自动添加Menubarvalue/onValueChange活动菜单移除改为逐个Menu.Root用open控制若有用到需重构通常没人用MenubarlooploopFocus重命名ToggleGroup / ToolbarrovingFocus{false}移除roving focus 恒开loop→loopFocus删除 / 重命名ContextMenu.Rootmodal移除删除ContextMenu.Triggerdisabled移除删除触发器禁用改由自己控制DropdownMenu/ContextMenu 菜单项Radix 选中即关闭菜单closeOnClick在 CheckboxItem/RadioItem 上默认 FALSE行为差异FLAG仅在用户要求时添加closeOnClickNavigationMenudelayDuration(200)、skipDelayDuration、viewportdelay(50) closeDelayviewport prop 消失由 Positioner 承担重命名/删除FLAG 200→50 的悬停延迟手感变化注意这张表里有两条是行为差异而非编译错误closeOnClick默认 false 意味着“点击复选/单选菜单项后菜单不自动关闭”Radix 下则会关闭Tabs 默认手动激活意味着点击 tab 不再自动切换面板。SKILL.md 的 Hard rules 明确规定行为差异一律 FLAG、绝不静默修补目标是产出“与 shadcn base registry 一致的惯用 Base UI”。3.4 其余零散项组件Radix propBase UI 去向调用点动作Avatar.ImagedelayMsdelay重命名ScrollAreatypealways\|scroll\|...移除删除Separatordecorative移除删除DirectionProviderdirdirection重命名4. 回调签名规则Callback Signature Rule文档单列一节说明回调签名的一般规律Base UI 的回调普遍新增一个 event-details 参数onOpenChange(open, eventDetails) onValueChange(value, eventDetails)由此推出两条实操结论已有的单参 handler 保持不变、依然类型安全TS 允许传参更少的函数曾经使用 Radix 事件参数的 handleronValueChange(value, event)这种必须对照对应组件族的参考文件逐一复查。第 3.1 节 Select 的加宽就是这一规则的反例提醒参数个数不变但类型变宽string→string | nulltypecheck 仍会失败不能依赖“单参函数天然兼容”这一点。5. 标准排查流程Sweep Procedure文档给出三步流程配合 SKILL.md 的整体迁移纪律使用grep 应用代码components/ui之外的部分逐个搜索上表左列的每个 token 外加asChild逐文件修复调用点每修完一个文件立即 typecheck不要攒批量提交把报错定位到文件粒度凡是在清单中被标记FLAG的项Tabs 手动激活、菜单项不点击关闭、NavigationMenu 50ms 延迟、TooltipdisableHoverableContent无等价物、Sliderinverted等一律写入迁移报告作为行为差异behavior delta绝不静默修补。报告落在项目根目录的.migration/component.md每个组件一个文件结构固定为Changed/Left alone/Behavior changes/Verify by hand四节见 SKILL.md 的 Verify and report 一节。渐进式迁移时这一步对应 SKILL.md 流程中的“repoint consumers ONE AT A TIMEimports the call-site props inconsumer-props.mdtypecheck each”——调用点改造是消费者切换到新 wrapper 导入时同步完成的那半份工作。6. 映射的验证方式以类型定义为准以仓库双注册表为旁证文档强调“when in doubt, checknode_modules/base-ui/react/**/*.d.ts, never guess”。在本仓库内还有两条独立的验证路径双注册表 diffapps/v4/registry/bases 中radix/与base/两套包装器逐文件对照。例如 Base 版 accordion.tsx 使用AccordionPrimitive.Item的value数组语义与data-starting-style/ending-style动画钩子而 Radix 版对应typesingle与data-[stateopen]——两套文件并排阅读即可复核第 3.1 节的每一条。示例代码apps/v4/examples/base/ 提供的是迁移后的“目标态”调用方式可直接作为调用点改造的参照实现。需要说明的适用前提本文清单基于base-ui/react1.6.0的类型定义核对文档首行注明若升级 Base UI 版本个别 prop 名称或默认值可能变化应以新版本的.d.ts为准重新过一遍这份清单。7. 小结调用点改造是 Radix → Base UI 迁移中“CLI 帮不上忙”的部分包装器可以自动化交付但asChild、type/collapsible、position、delayDuration、onOpenAutoFocus这一类 props 只能在业务代码里逐个替换。本文的清单给出了一张可直接 grep 的对照表、一条asChild → render的通用规则、一条回调签名规则以及“grep → 逐文件 typecheck → FLAG 行为差异”的可执行流程配合仓库内radix/与base/双注册表源码可以在迁移每个组件后对映射做二次验证确保应用代码在保留原有行为意图的前提下切换到 Base UI 语义。【免费下载链接】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),仅供参考
返回列表