ARTICLE DETAIL

资讯详情

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

refine 中 Ant Design ListButton 完整指南:从列表页跳转到权限控制

refine 中 Ant Design ListButton 完整指南:从列表页跳转到权限控制 refine 中 Ant Design ListButton 完整指南从列表页跳转到权限控制【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refineListButton是 refine 面向 Ant Design 封装的一个导航型按钮组件用于在详情页Show、编辑页Edit等场景中一键跳回当前资源的列表页。它底层复用useNavigation的list方法并自动根据资源名称生成按钮文案开箱即用同时支持自定义跳转目标、纯图标模式以及接入 access control 权限体系。本文以 v3 版本文档documentation/versioned_docs/version-3.xx.xx/api-reference/antd/components/buttons/list.md为主体结合当前仓库中的源码实现与共用测试套件完整讲解它的用法、属性、内部原理与测试保障。ListButton 是什么ListButton基于 Ant Design 的Button组件构建本质是一个带导航语义的链接型按钮。它的典型使用场景是在Show详情页面提供返回列表按钮在Edit编辑页面提供返回列表的入口任何需要回到某个资源列表页的自定义页面。从仓库源码看Ant Design 适配层对它的实现非常薄核心逻辑全部交给 core 包UI 组件packages/antd/src/components/buttons/list/index.tsx类型定义packages/antd/src/components/buttons/types.ts// packages/antd/src/components/buttons/list/index.tsx 中导出 export const ListButton: React.FCListButtonProps ({ resource: resourceNameFromProps, hideText false, accessControl, meta, children, onClick, ...rest }) { ... }可以看到它接收resourcev3 文档中名为resourceNameOrRouteName、hideText、accessControl、meta、onClick等属性并把剩余 props 原样透传给 Ant Design 的Button。Swizzle 支持该组件支持通过refine CLI的 swizzle 命令拷贝到项目本地进行深度定制对应文档中的swizzle: true标记CLI 实现位于 packages/cli。快速上手在 Show 页面中放置返回列表按钮最典型的用法是把ListButton /放进Show组件的headerButtons插槽这样详情页头部就会自动出现一个返回列表按钮// visible-block-start import { useShow } from pankod/refine-core; import { Show, Typography, // highlight-next-line ListButton, } from pankod/refine-antd; const { Title, Text } Typography; const PostShow: React.FC () { const { queryResult } useShowIPost(); const { data, isLoading } queryResult; const record data?.data; return ( // highlight-next-line Show headerButtons{ListButton /} isLoading{isLoading} Title level{5}Id/Title Text{record?.id}/Text Title level{5}Title/Title Text{record?.title}/Text /Show ); }; interface IPost { id: number; title: string; } // visible-block-end说明上述示例使用 v3 时代的包名pankod/refine-antd、pankod/refine-core在当前仓库的 v4/v5 源码中对应包已更名为refinedev/antd、refinedev/core用法保持一致。点击该按钮后refine 会调用useNavigation的list方法跳转到当前资源posts的列表页路由如/posts。按钮文案自动生成文档中特别注明按钮文字由 refine 根据resource对象的name属性自动定义。结合源码可以看得更具体——useNavigationButton中 list 动作的 label 生成逻辑为// packages/core/src/hooks/button/navigation-button/index.tsx#L79-L88 const label props.action list ? translate( ${identifier ?? props.resource}.titles.list, getUserFriendlyName( resource?.meta?.label ?? identifier ?? props.resource, plural, ), ) : translate(buttons.${props.action}, humanize(props.action));即优先使用 i18n 键resource.titles.list的翻译未配置翻译时回退到资源名或meta.label的人性化复数形式——例如资源名为posts时按钮显示为Posts。这也意味着它天然支持多语言。属性详解resourceNameOrRouteName跳转目标由resourceNameOrRouteName属性决定最终生成的地址为resourceNameOrRouteName/list。默认情况下ListButton使用 resource 对象的name属性作为点击后的跳转端点。// visible-block-start import { ListButton } from pankod/refine-antd; const MyListComponent () { return ListButton resourceNameOrRouteNamecategories /; }; // visible-block-end点击该按钮会触发useNavigation的list方法并跳转到/categories。版本演化提示在 v3 文档本文主体中该属性名为resourceNameOrRouteName而当前仓库源码已将入参更名为resource并支持使用资源的identifier代替name。类型定义见 packages/ui-types/src/types/button.tsxexport type RefineButtonResourceProps { /** * Resource name for API data interactions. identifier of the resource can be used instead of the name of the resource. * default Inferred resource name from the route */ resource?: string; ... };未显式传入时useResourceParams会从当前路由推断资源见 packages/core/src/hooks/button/navigation-button/index.tsx。hideText用于控制是否显示按钮文字。设为true时只显示图标// visible-block-start import { ListButton } from pankod/refine-antd; const MyListComponent () { return ( ListButton // highlight-next-line hideText{true} / ); }; // visible-block-end对应 UI 层实现hideText默认为false渲染时!hideText (children ?? label)决定文字是否输出packages/antd/src/components/buttons/list/index.tsx。ListButton 的图标为 Ant Design 的BarsOutlined列表图标。类型定义中该属性位于RefineButtonCommonPropspackages/ui-types/src/types/button.tsx。accessControl该属性用于控制权限校验行为仅在向Refine/提供了accessControlProvider时生效enabled是否启用访问控制检查hideIfUnauthorized当用户对目标资源没有权限时是否直接隐藏按钮。import { ListButton } from pankod/refine-antd; export const MyListComponent () { return ( ListButton accessControl{{ enabled: true, hideIfUnauthorized: true }} / ); };类型层面accessControl的默认值为{ enabled: true }packages/ui-types/src/types/button.tsx。实际校验由useButtonCanAccess完成它会调用 access control provider 的can方法action 为list校验失败时按钮默认进入禁用态并显示reason作为title提示若hideIfUnauthorized为true则直接不渲染对应 packages/core/src/hooks/button/navigation-button/index.tsx 及 UI 层的if (isHidden) return null逻辑。其他可用属性Ant Design Button 全部属性由于...rest会透传type、size、danger、loading等原生ButtonProps均可直接使用children自定义按钮文字优先级高于自动生成的 labelonClick点击回调若按钮处于禁用态点击会被拦截e.preventDefault()且不触发回调disabled/hidden分别强制禁用与隐藏按钮meta生成目标 URL 时携带的附加 meta 数据。源码级原理点击后发生了什么1. 组件渲染层antd 适配packages/antd/src/components/buttons/list/index.tsx 完整实现了渲染逻辑const { to, label, title, hidden, disabled, LinkComponent } useListButton({ resource: resourceNameFromProps, meta, accessControl, }); const isDisabled disabled || rest.disabled; const isHidden hidden || rest.hidden; if (isHidden) return null; return ( LinkComponent to{to} replace{false} onClick{(e) { if (isDisabled) { e.preventDefault(); return; } if (onClick) { e.preventDefault(); onClick(e); } }} Button icon{BarsOutlined /} disabled{isDisabled} title{title} >export const useListButton ( props: PrettifyOmitNavigationButtonProps, action | id, ) useNavigationButton({ ...props, action: list });在 navigation-button/index.tsx 中跳转地址由 action 决定const to React.useMemo(() { if (!resource) return ; switch (props.action) { case create: case list: return navigation${props.action}Url; ... } }, [resource, id, props.meta, navigation[${props.action}Url]]);对于list动作最终调用navigation.listUrl(resource, meta)——这正是useNavigation暴露的list方法与文档中使用useNavigation的list方法的描述完全对应从而生成/{resourceName}/list形式的完整路由如/categories。3. 类型契约ListButtonProps的完整类型为RefineListButtonPropsButtonPropspackages/antd/src/components/buttons/types.ts其构成如下packages/ui-types/src/types/button.tsxexport type RefineListButtonProps TComponentProps extends {} Recordstring, unknown, TExtraProps extends {} {}, RefineButtonCommonProps // hideText RefineButtonResourceProps // resource / accessControl RefineButtonLinkingProps // onClick RefineButtonURLProps // meta TComponentProps // 在这里即 antd 的 ButtonProps TExtraProps {};测试保障共用测试套件ListButton的测试位于 packages/antd/src/components/buttons/list/index.spec.tsx它直接复用了refinedev/ui-tests中的共用测试套件import { buttonListTests } from refinedev/ui-tests; import { ListButton } from ./; describe(List Button, () { buttonListTests.bind(this)(ListButton); });共用测试套件定义在 packages/ui-tests/src/tests/buttons/list.tsx覆盖了以下行为契约基础渲染按钮可正常渲染且默认非禁用测试标识存在data-testidRefineButtonTestIds.ListButton禁用态传入disabled后按钮禁用且点击不会触发onClick隐藏态传入hidden后按钮不渲染文案优先级children优先渲染未传 children 时按资源 label 生成如资源meta.label test时显示 Tests纯图标模式hideText时资源名文字不出现权限控制矩阵覆盖全局accessControlProvider配置、按钮级accessControl覆盖、hideIfUnauthorized全局/局部开关、无权限时禁用并显示 reason 等 10 余种组合点击回调点击后onClick被正确调用。这保证了无论使用哪种 UI 适配层Ant Design、MUI、Mantine、Chakra UI 等ListButton 的导航、禁用、隐藏与权限行为都保持一致。常见问题与最佳实践如何在多个资源间跳转在非当前资源上下文如 Dashboard中使用时务必显式传入resourceNameOrRouteNamev3或resource当前版本避免依赖路由推断。如何自定义文案优先使用 i18n 键resource.titles.list临时场景直接传children即可覆盖自动 label。权限不足时想要隐藏而不是禁用设置accessControl{{ hideIfUnauthorized: true }}注意只有配置了accessControlProvider时该行为才会生效。按钮文字与列表页标题联动由于 label 与列表页标题共享resource.titles.list翻译键保持文案一致性的同时只需维护一处配置。综上ListButton是一个薄封装、强约定的组件文档层告诉你如何即插即用地返回列表页源码层则揭示了它如何通过useListButton → useNavigationButton(action: list) → useNavigation.listUrl()的调用链完成路由生成并通过共用测试套件保证跨 UI 适配层的行为一致。理解这层实现后无论是使用默认行为、定制跳转目标还是接入权限体系都能做到心中有数。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表