ARTICLE DETAIL

资讯详情

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

Refine CloneButton 完整指南:用 Chakra UI 一键跳转“克隆/复制”创建页

Refine CloneButton 完整指南:用 Chakra UI 一键跳转“克隆/复制”创建页 Refine CloneButton 完整指南用 Chakra UI 一键跳转“克隆/复制”创建页【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本文以 Refine 3.x 官方文档中 Chakra UICloneButton章节为核心结合当前仓库packages/chakra-ui与packages/core的源码实现系统讲解克隆按钮的用途、底层路由原理、全部核心属性recordItemId、resourceNameOrRouteName、hideText、accessControl等、访问控制机制与自定义方式帮助你在 admin panel / B2B 应用中快速实现“基于已有记录快速创建新记录”的常见交互。CloneButton 是什么一行代码完成“克隆式新建”在业务后台中“复制某条记录作为新记录”是非常高频的交互用户查看某篇帖子或某条分类后希望以它为模板新建一条几乎相同的数据只需修改少量字段。Refine 的CloneButton正是为这个场景设计的导航按钮。从 源码注释 可以确认它的定位它基于 Chakra UI 的Button组件渲染内部通过useCloneButton核心包 useNavigation 的clone方法计算目标地址点击后应用会被重定向到“带记录 id 的资源 clone 路由”例如/posts/clone/123。也就是说它本质上是一个“携带当前记录 id 跳转到创建页”的智能链接按钮把「查 id → 拼路由 → 跳转」这一串样板代码封装成了一个组件。底层原理从点击到/posts/clone/123的完整调用链为了正确使用有必要先理解按钮背后的路由是怎么算出来的。整个链路可以拆成四层组件层CloneButton 实现 接收resource即文档中的resourceNameOrRouteName、recordItemId、accessControl、meta等参数调用useCloneButton。Hook 层packages/core/src/hooks/button/index.tsx 中useCloneButton只是useNavigationButton({ ...props, action: clone })的简写与show、edit、create、list共用同一套导航按钮逻辑。导航计算层navigation-button 实现 通过useResourceParams从路由推断当前资源与 idcreate动作除外再调用navigation.cloneUrl(resource, id, meta)生成to目标地址。路由组装层useNavigation 源码 中的cloneUrl会先用encodeURIComponent编码 id再从资源定义中查找clone动作路由如posts.clone: /posts/clone/:id最终组合出完整路径。一个值得注意的实现细节在 navigation-button 源码 中label默认通过translate(buttons.clone, humanize(clone))得到即按钮文案受 i18n 与textTransformers配置影响同时按钮最终渲染为LinkComponent由useLink提供通常是 react-router 的Link包裹的 ChakraButton/IconButton因此它是一个真正的a链接而非模拟点击的button——这也让中间键/新标签页打开天然可用。快速上手在列表页为每一行添加克隆按钮官方文档给出的典型用法是在表格的 Actions 列中放置CloneButton并传入当前行的 id。以下示例完整保留了文档中的用法基于 v3 的pankod/refine-chakra-ui包名配合pankod/refine-react-table渲染表格import { List, TableContainer, Table, Thead, Tr, Th, Tbody, Td, CloneButton, // 高亮引入克隆按钮 } from pankod/refine-chakra-ui; import { useTable, ColumnDef, flexRender } from pankod/refine-react-table; const PostList: React.FC () { const columns React.useMemoColumnDefIPost[]( () [ { id: id, header: ID, accessorKey: id, }, { id: title, header: Title, accessorKey: title, }, { id: actions, header: Actions, accessorKey: id, cell: function render({ getValue }) { return ( // 高亮把当前行的 id 传给克隆按钮 CloneButton recordItemId{getValue() as number} / ); }, }, ], [], ); const { getHeaderGroups, getRowModel } useTable({ columns, }); return ( List TableContainer Table variantsimple whiteSpacepre-line Thead {getHeaderGroups().map((headerGroup) ( Tr key{headerGroup.id} {headerGroup.headers.map((header) ( Th key{header.id} {!header.isPlaceholder flexRender( header.column.columnDef.header, header.getContext(), )} /Th ))} /Tr ))} /Thead Tbody {getRowModel().rows.map((row) ( Tr key{row.id} {row.getVisibleCells().map((cell) ( Td key{cell.id} {flexRender( cell.column.columnDef.cell, cell.getContext(), )} /Td ))} /Tr ))} /Tbody /Table /TableContainer /List ); }; interface IPost { id: number; title: string; }配套的Refine配置中需要为该资源注册create页面克隆最终落在创建页上const App () { return ( Refine notificationProvider{RefineChakra.notificationProvider()} resources{[ { name: posts, list: PostList, create: ClonePage, // 克隆按钮跳转到的目标页面 }, ]} / ); };核心属性详解recordItemId指定要克隆的记录 idrecordItemId用于把记录 id 追加到路由路径的末尾。官方文档示例import { CloneButton } from pankod/refine-chakra-ui; const MyCloneComponent () { return CloneButton colorSchemeblack recordItemId123 /; };点击后按钮触发useNavigation的clone方法将应用重定向到/posts/clone/123。注意CloneButton默认会从当前路由读取 id 信息比如你在/posts/edit/1页面它自动带上1只有在路由中无法推断、或需要覆盖时才需要显式传入recordItemId。这一点在 ui-types 类型定义 中标注为“默认读取 URL 中的:id”。resourceNameOrRouteName指定跳转到哪个资源的 clone 路由该属性用于把应用重定向到指定资源的/clone端点。默认情况下应用会使用资源对象name属性所定义的/clone路由。import { CloneButton } from pankod/refine-chakra-ui; const MyCloneComponent () { return ( CloneButton colorSchemeblack resourceNameOrRouteNamecategories recordItemId2 / ); };此时点击按钮会跳转到/categories/clone/2而不是当前所在的/posts资源。版本差异提示本文档基于 3.x包名pankod/refine-chakra-ui该属性名为resourceNameOrRouteName而当前仓库源码v4 风格中CloneButton 实现 已将该 prop 命名为resource并且 ui-types 类型 说明可以使用资源的identifier代替name来指定数据交互目标。迁移到新版本时只需把属性名替换为resource即可。hideText只显示图标、隐藏文字当hideText为true时按钮只显示图标不显示文字。在窄列表、工具栏空间紧张的场景下非常实用import { CloneButton } from pankod/refine-chakra-ui; const MyCloneComponent () { return CloneButton colorSchemeblack hideText /; };从 组件源码 可以看到它的实现方式hideText为真时渲染 Chakra 的IconButtonvariantoutline仅保留IconSquarePlus图标默认 20px可通过svgIconProps覆盖并把label作为aria-label以维持可访问性否则渲染带leftIcon的常规Button文字部分优先取children缺省时使用label。accessControl接入权限控制accessControl用于控制按钮的访问权限行为仅在向Refine/提供了accessControlProvider时生效详见 refine-config。它有两个子属性enabled是否启用访问控制检查可跳过检查hideIfUnauthorized当用户无权访问该资源时是否直接隐藏按钮。import { CloneButton } from pankod/refine-chakra-ui; export const MyListComponent () { return ( CloneButton accessControl{{ enabled: true, hideIfUnauthorized: true }} / ); };源码级行为说明按钮的权限逻辑集中在 navigation-button 实现 的useButtonCanAccess中它与全局accessControlProvider.options.buttons配置共同决定三个输出disabled无权访问时按钮被禁用同时title会显示 provider 返回的拒绝原因例如 “Access Denied”hiddenhideIfUnauthorized为真且无权时组件直接返回null不渲染title悬停提示文案。在 组件源码 中isDisabled disabled || rest.disabled且点击事件里若按钮被禁用会先e.preventDefault()阻止跳转isHidden为真时直接return null。也就是说「禁用并提示原因」与「直接隐藏」两种策略你都可以按业务需要选择。另外需要注意权限检查的 action 是create而非clone——因为克隆的语义等价于“创建一条基于旧记录的新记录”。这一点在 通用测试用例 中体现得很清楚测试里的can回调判断的是action create params?.id 1时返回can: false。其他可用属性与透传机制除了文档重点讲解的四个属性外结合 ui-types 的RefineCloneButtonProps与 Chakra 组件的类型定义CloneButton还支持children自定义按钮文字覆盖默认的 “Clone” 文案测试用例should render text by children验证了该行为onClick自定义点击处理器类型为React.PointerEventHandlerHTMLButtonElement组件源码中若传了onClick会先preventDefault再调用方便你拦截导航做自定义逻辑disabled/hidden直接禁用或隐藏按钮svgIconProps覆盖默认图标IconSquarePlus的属性如尺寸、颜色meta构造路由 URL 时使用的额外元数据会传入cloneUrl的第三个参数其余属性colorScheme、size、variant等通过...rest透传给 Chakra 的Button/IconButton因此 Chakra UI 按钮的全部能力都可用。无障碍与测试钩子组件在两种渲染形态下都设置了data-testid{RefineButtonTestIds.CloneButton}供端到端测试与组件测试定位aria-label{label}图标形态与title保证屏幕阅读器与悬停提示可用图标形态下文字没有消失而是转移到了aria-label这是刻意为之的无障碍设计。通用按钮测试集 是验证这些行为的官方用例集合packages/chakra-ui的 clone/index.spec.tsx 直接复用了它覆盖了默认渲染、disabled拦截点击、hidden不渲染、test-id 存在、children 覆盖文案、hideText仅图标、全局/局部访问控制的各种组合禁用原因、隐藏、显式关闭、prop 覆盖全局配置以及点击后跳转/posts/clone/1、自定义资源跳转/categories/clone/1等路由行为。通过 Swizzle 深度自定义如果默认样式或结构不满足需求文档提供了标准做法使用refine CLI的 swizzle 功能把这个组件“解包”到你的项目中然后自由修改。CLI 的完整命令与交互说明见 refine CLI 文档。Swizzle 后你会得到一个可编辑的本地组件副本可在此基础上更换图标默认IconSquarePlus来自tabler/icons-react改变按钮形态variant默认outline调整默认文案或接入自己的 i18n key增加确认弹窗、埋点等业务逻辑。小结CloneButton是 Refine 按钮家族中“导航类”按钮的典型代表它把「根据当前/指定资源与记录 id 计算 clone 路由 → 渲染成带权限控制的链接按钮 → 携带无障碍与测试钩子」整套能力封装成了一个声明式组件。理解它的调用链组件 →useCloneButton→useNavigationButton→cloneUrl后EditButton、ShowButton、CreateButton、ListButton的底层逻辑也能触类旁通因为它们共享同一套 navigation-button 实现只是action不同。核心参考路径速览组件实现packages/chakra-ui/src/components/buttons/clone/index.tsx属性类型packages/chakra-ui/src/components/buttons/types.ts通用类型定义packages/ui-types/src/types/button.tsx核心 Hookpackages/core/src/hooks/button/index.tsx、navigation-button路由生成packages/core/src/hooks/navigation/index.ts测试用例packages/ui-tests/src/tests/buttons/clone.tsx、packages/chakra-ui/src/components/buttons/clone/index.spec.tsx相关文档useNavigation、accessControlProvider、refine-config【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表