Refine Chakra UI Breadcrumb 组件使用指南:基于 useBreadcrumb 的层级导航面包屑
【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine
面包屑(Breadcrumb)用于展示当前页面在应用层级结构中的位置,并允许用户快速返回上层页面。本文以 Refine(v3.xx.xx)的 Chakra UI 集成包中的<Breadcrumb>组件为核心,讲解它的数据来源、全部配置属性(breadcrumbProps、showHome、hideIcons等)、嵌套资源与 i18n 行为,并结合仓库源码剖析其底层实现,帮助你在管理后台、仪表盘等内部工具中快速落地可用的面包屑导航。
组件定位:基于 Chakra UI 与 useBreadcrumb 的封装
Refine 的 Chakra UI 包中提供了开箱即用的<Breadcrumb>组件。根据版本 3.xx.xx 的官方文档,该组件构建在 Chakra UI 的 Breadcrumb 组件之上,底层数据则来自 Refine Core 的useBreadcrumbHook。
也就是说,它完成了两件事:
- 数据层:通过
useBreadcrumb根据当前路由解析出的 resource 与 action,自动生成面包屑条目数组; - 展示层:把生成的条目渲染为 Chakra UI 的
Breadcrumb/BreadcrumbItem/BreadcrumbLink结构。
在 Breadcrumb 组件实现 中可以看到核心逻辑:
export const Breadcrumb: React.FC<BreadcrumbProps> = ({ breadcrumbProps, showHome = true, hideIcons = false, meta, minItems = 2, }) => { const { breadcrumbs } = useBreadcrumb({ meta }); const Link = useLink(); if (breadcrumbs.length < minItems) return null; const { resources } = useResourceParams(); const rootRouteResource = matchResourceFromRoute("/", resources); return ( <ChakraBreadcrumb mb="3" {...breadcrumbProps}> {showHome && rootRouteResource?.found && ( <BreadcrumbItem> <Link to="/"> {rootRouteResource?.resource?.meta?.icon ?? <IconHome size={20} />} </Link> </BreadcrumbItem> )} {breadcrumbs.map(({ label, icon, href }) => { return ( <BreadcrumbItem key={label}> {!hideIcons && icon} {href ? ( <BreadcrumbLink ml={2} as={Link as any} to={href}> {label} </BreadcrumbLink> ) : ( <BreadcrumbLink ml={2}>{label}</BreadcrumbLink> )} </BreadcrumbItem> ); })} </ChakraBreadcrumb> ); };从源码结构可以提炼出几个关键事实:
- 默认渲染阈值
minItems = 2:当面包屑条目少于 2 个时组件直接返回null(不渲染); - 默认
showHome = true:当存在匹配/根路由的 resource 时,在最前面渲染“首页”入口; - 每个条目由
{ label, icon, href }三部分驱动:href存在时渲染为链接,否则渲染为纯文本; - 图标通过
!hideIcons && icon控制,可通过hideIcons关闭。
数据来源:useBreadcrumb 如何生成条目
面包屑的内容完全由资源定义(resources)与当前路由推断而来。useBreadcrumb返回的breadcrumbs是一个对象数组,每个对象包含:
| 属性 | 说明 |
|---|---|
| label | 资源的显示名称 |
| href | 资源 list 页面的路由(可选) |
| icon | 资源的图标(可选) |
其类型定义在useBreadcrumb实现 中:
export type BreadcrumbsType = { label: string; href?: string; icon?: React.ReactNode; };生成流程可以概括为(见 packages/core/src/hooks/breadcrumb/index.ts):
- 通过
useResourceParams()获取当前路由对应的action、resource与全部resources; - 若当前没有匹配的 resource(
!resource?.name),直接返回空数组; addBreadcrumb递归处理资源层级:若资源的meta.parent存在,会先递归添加父级条目;- 通过
getActionRoutesFromResource找到该资源的list路由,并用composeRoute组合出完整href; - 若当前
action不是list(如create、edit、show),再追加一个动作条目,其文本通过translate("actions.${action}")获取。
以一个简单的posts资源为例:
[ { name: "posts", icon: <div>icon</div>, list: () => <div>List Page</div>, create: () => <div>Create Page</div>, }, ];- 在
posts的list页面,面包屑为[{ label: "Posts", href: "/posts", icon }]; - 在
posts的create页面,面包屑为[{ label: "Posts", href: "/posts", icon }, { label: "Create" }]。
注意两个边界情况:如果资源没有定义icon,条目的icon为undefined;如果资源没有定义list页面,条目的href为undefined,此时<Breadcrumb>会将其渲染为纯文本而非链接(与useBreadcrumb文档中的说明一致,见 useBreadcrumb 文档)。
嵌套资源(Nested resource)
当资源存在父子层级时,useBreadcrumb会根据meta.parent(或parentName)递归展开父级条目。例如:
[ { name: "cms" }, { name: "users", parentName: "cms", list: () => <div>List Page</div>, create: () => <div>Create Page</div>, }, ];users的list页面会得到[{ label: "Cms" }, { label: "Users", href: "/users" }];users的create页面会得到[{ label: "Cms" }, { label: "Users", href: "/users" }, { label: "Create" }]。
这在多层级后台(如“系统管理 → 用户管理 → 新建用户”)中非常实用,用户始终能沿面包屑返回任意上层。
在 CRUD 页面中使用<Breadcrumb>
<Breadcrumb>最常见的用法是通过 CRUD 组件的breadcrumb属性注入,例如在Show、List、Create、Edit中:
import { Show, Breadcrumb } from "@pankod/refine-chakra-ui"; const PostShow: React.FC = () => { return ( <Show breadcrumb={<Breadcrumb />}> <p>Rest of your page here</p> </Show> ); };从 Show 组件实现 可以看到,CRUD 组件对breadcrumb的处理遵循“就近优先”原则:
const breadcrumb = typeof breadcrumbFromProps === "undefined" ? globalBreadcrumb : breadcrumbFromProps;即:组件级breadcrumb属性优先;未设置时回退到全局配置options.breadcrumb(来自useRefineContext);若两者都未定义,则渲染默认的<Breadcrumb />。List、Create、Edit组件的处理方式一致(见 crud/list/index.tsx 与 crud/show/index.tsx)。
如果需要为整个应用统一配置面包屑,可以在<Refine>的options中设置全局值,相关说明见 refine-config 文档:
<Refine options={{ breadcrumb: <Breadcrumb />, // 或 breadcrumb: false 以全局禁用 }} />注意:单个 CRUD 组件中设置的
breadcrumb会覆盖全局options.breadcrumb的值。
属性详解
breadcrumbProps
<Breadcrumb>内部最终渲染的是 Chakra UI 的Breadcrumb组件,因此所有 Chakra UI 的面包屑 props 都可以通过breadcrumbProps透传。例如自定义分隔符:
import { Show, Breadcrumb } from "@pankod/refine-chakra-ui"; const PostShow: React.FC = () => { return ( <Show breadcrumb={<Breadcrumb breadcrumbProps={{ separator: "-" }} />}> <p>Rest of your page here</p> </Show> ); };在 组件源码 中,breadcrumbProps被展开到 Chakra UI 的Breadcrumb上(<ChakraBreadcrumb mb="3" {...breadcrumbProps}>),同时组件自身固定设置了mb="3"下边距。这意味着你可以通过breadcrumbProps传入 Chakra UIBreadcrumb支持的任何属性(如separator、spacing、fontSize等)。
showHome
如果应用中配置了DashboardPage,根路由/对应一个 resource,那么默认情况下<Breadcrumb>会在层级最顶部渲染一个“首页”按钮。若你不想展示首页按钮,可将其设为false:
<Show breadcrumb={<Breadcrumb showHome={false} />}> <p>Rest of your page here</p> </Show>其底层逻辑在 组件源码:通过matchResourceFromRoute("/", resources)判断是否存在根路由资源,存在且showHome为true时才渲染首页条目;首页链接的图标优先取该资源的meta.icon,否则回退为IconHome。
hideIcons
默认情况下,面包屑会在每个条目旁显示资源的icon。若不需要显示资源图标,设置hideIcons为true:
<Show breadcrumb={<Breadcrumb hideIcons />}> <p>Rest of your page here</p> </Show>在 源码 中对应{!hideIcons && icon},仅影响条目图标,不会影响首页入口。
minItems
这是一个在文档的 PropsTable 之外、但已存在于源码与共享类型中的属性(见 ui-types 类型定义)。它表示渲染面包屑所需的最小条目数:
// 只有条目数 >= 2 时才渲染(默认值) <Breadcrumb minItems={2} /> // 即使只有一个条目也渲染 <Breadcrumb minItems={1} />当breadcrumbs.length < minItems时组件返回null(实现位置)。该行为也被共享测试覆盖,见下文“测试验证”。
meta
meta用于在路由生成过程中附加额外参数,最终会传给useBreadcrumb({ meta }),并参与composeRoute的 URL 组合(见 useBreadcrumb 实现)。典型场景是为带动态参数的嵌套路由补全参数值。
i18n 支持
面包屑的文本展示遵循以下优先级(详见 useBreadcrumb 实现):
- 若资源定义了
meta.label,直接使用; - 否则通过
translate("${resourceName}.${resourceName}", humanize(name))进行翻译,回退值为资源名的人性化形式(如posts→Posts); - CRUD 动作(
create/edit/show等)的标签通过translate("actions.${action}")获取,例如actions.create; - 若翻译文件中缺少
actions.${action}键,代码会通过warnOnce输出一条警告,并回退到translate("buttons.${action}")或动作名的人性化形式(源码位置)。
因此,要为面包屑提供中文等多语言支持,只需要在你的 i18n 翻译文件中添加形如actions.create: "创建"、actions.edit: "编辑"的键值即可。
自定义与 Swizzle
官方文档明确提示该组件支持swizzle(组件定制化):你可以使用refine CLI将组件源码“弹出”到你的项目中,然后按需修改。例如:
npm run refine swizzle选择 Chakra UI 的Breadcrumb组件后,即可在项目内获得一份可编辑的组件副本,自由调整结构、样式或扩展逻辑,而无需改动包源码。
测试验证:行为有据可查
仓库中为面包屑提供了两层测试,可用于验证上述行为:
- 共享测试packages/ui-tests/src/tests/breadcrumb.tsx:覆盖了“条目数小于
minItems时不渲染”“条目数达到minItems时渲染”“渲染资源名”“渲染链接(href指向 list 路由)”“渲染资源图标”“hideIcons隐藏图标”等用例,这套测试被 Ant Design、MUI、Mantine 等所有 UI 包共用; - Chakra 专属测试packages/chakra-ui/src/components/breadcrumb/index.spec.tsx:额外验证了“默认渲染首页图标”“
showHome={false}时不渲染首页图标”“渲染资源名与动作名”。
这些测试直接证明了:资源条目链接指向其list路由(expect(link).toHaveAttribute("href", "/posts"))、hideIcons与showHome的开关行为,以及minItems的渲染阈值。
完整属性速查
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
breadcrumbProps | ChakraBreadcrumbProps | — | 透传给 Chakra UIBreadcrumb的 props(如separator) |
showHome | boolean | true | 存在根路由资源时是否显示首页按钮 |
hideIcons | boolean | false | 是否隐藏资源图标 |
meta | Record<string, string \| number> | — | 路由生成过程中的附加参数 |
minItems | number | 2 | 渲染所需的最小条目数,少于该值则不渲染 |
完整类型定义可参考 RefineBreadcrumbProps。
小结
Refine 的 Chakra UI<Breadcrumb>组件将“路由 → 资源 → 层级 → 文案”的推断逻辑封装在useBreadcrumb中,配合 Chakra UI 的成熟样式体系,让你无需手写任何导航逻辑即可获得与资源定义、i18n、全局配置保持一致的层级导航。无论是单层资源、嵌套资源,还是需要关闭首页入口、隐藏图标、自定义分隔符,都可以通过组件属性在数行代码内完成;当默认行为无法满足需求时,还可以通过 refine CLI 进行 swizzle 定制。
【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考