
Refine v5 Mantine 指南深入掌握Show组件构建专业的详情展示页【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本文是 Refine v5 官方文档中 MantineShow组件文档 的深度解读与实战指南。Show是 Refine Mantine 集成提供的基础视图Basic Views组件之一专用于构建数据详情页展示单条记录。本文将从组件的定位与基础用法出发逐一讲解其全部属性title、resource、canDelete、canEdit、recordItemId、dataProviderName、goBack、isLoading、breadcrumb、wrapperProps、contentProps、headerButtons等并结合仓库源码与单元测试揭示其底层实现原理。读完本文你将能够熟练使用Show组件快速搭建、深度定制 Refine Mantine 应用中的详情展示页面。Show组件的定位纯布局层无业务逻辑Show为详情页提供页面布局与外壳它本身不包含任何业务逻辑只负责在布局层面提供额外的功能例如顶部标题区可自定义标题、面包屑、返回按钮右侧头部操作按钮列表、编辑、删除、刷新按钮内容区渲染业务字段底部操作按钮区加载中遮罩LoadingOverlay。这一点在源码中有清晰的印证。在 packages/mantine/src/components/crud/show/index.tsx 中Show组件是一个典型的组合型函数组件它通过useResourceParams读取路由解析出的 resource 与 id通过useTranslate、useUserFriendlyName生成默认标题通过useBack/useGo处理返回与跳转最终将各按钮与内容区组合渲染在 Mantine 的Card容器中。组件的 props 类型定义在 packages/mantine/src/components/crud/types.ts其基类RefineCrudShowProps位于 packages/ui-types/src/types/crud.tsx#L280-L384是各 UI 集成Ant Design、Material UI、Chakra UI、Mantine中Show实现共享的基础类型。基础用法配合useShow展示记录详情Show通常与 Refine 核心包的useShowhook 配合使用useShow负责根据路由参数/posts/show/:id调用 data provider 获取单条记录Show负责页面布局与加载态。以下是一个完整的详情页示例原文示例摘自 show/index.mdimport { useShow } from refinedev/core; import { Show, MarkdownField } from refinedev/mantine; import { Title, Text } from mantine/core; const PostShow: React.FC () { const { result: post, query: { isLoading }, } useShowIPost(); return ( Show isLoading{isLoading} Title order{5}Id/Title Text mtsm{post?.id}/Text Title mtsm order{5} Title /Title Text mtsm{post?.title}/Text Title mtsm order{5} Content /Title MarkdownField value{post?.content} / /Show ); };对应的路由注册RefineMantineDemo resources{[ { name: posts, list: /posts, show: /posts/show/:id, }, ]} ReactRouter.Routes ReactRouter.Route path/posts/show/:id element{PostShow /} / /ReactRouter.Routes /RefineMantineDemo要点说明useShow返回的query.isLoading可直接传给Show isLoading{...}在数据加载期间组件会显示 Mantine 的LoadingOverlay遮罩源码见 show/index.tsx#L128MarkdownField是refinedev/mantine提供的字段组件用于渲染 Markdown 格式内容组件默认标题为Show {资源名单数名}例如资源为posts时显示 Show post且标题会经translate国际化处理支持{identifier}.titles.show翻译键。属性详解title自定义页面标题title允许在Show内添加自定义标题。如果未传入组件默认使用 Show 前缀加资源的单数名称通过useUserFriendlyName与getUserFriendlyName(identifier, singular)生成见 show/index.tsx#L176-L190。例如资源为posts时默认标题为 Show post。import { Show } from refinedev/mantine; import { Title } from mantine/core; const PostShow: React.FC () { return ( Show title{Title order{3}Custom Title/Title} pRest of your page here/p /Show ); };resource指定自定义资源Show默认从路由中读取resource信息。如果需要在自定义页面中使用其他资源可通过resource属性显式指定import { Show } from refinedev/mantine; const CustomPage: React.FC () { return ( Show resourcecategories pRest of your page here/p /Show ); };对应路由/custom/:id无需包含categories路径组件会以categories作为资源去解析。多个资源同名时的identifier如果你有多个同名资源可以传入资源的identifier而非name。identifier仅作为资源匹配的主键data provider 方法仍会使用Refine/组件中定义的资源name。更多信息可参考 Refine 组件 identifier 文档。canDelete 与 canEdit控制删除/编辑按钮canDelete与canEdit用于在Show内部添加删除和编辑按钮。如果资源本身带有canDelete或canEdit属性Refine 会默认添加相应按钮删除按钮点击后执行 data provider 提供的deleteOne方法通过useDelete编辑按钮点击后将用户重定向到记录的编辑页。从源码看按钮的可见性遵循如下规则show/index.tsx#L87-L92const hasList resource?.list !recordItemId; const isDeleteButtonVisible canDelete ?? (resource?.meta?.canDelete || deleteButtonPropsFromProps); const isEditButtonVisible canEdit ?? resource?.meta?.canEdit ?? !!resource?.edit;即组件上的canDelete/canEditprop 优先其次取资源 meta 中的canDelete/canEdit编辑按钮还会在资源配置了edit路由时显示。recordItemId存在时列表按钮会被隐藏。结合权限控制usePermissions动态控制按钮的示例import { Show } from refinedev/mantine; import { usePermissions } from refinedev/core; const PostShow: React.FC () { const { data: permissionsData } usePermissions(); return ( Show canDelete{permissionsData?.includes(admin)} canEdit{permissionsData?.includes(admin)} pRest of your page here/p /Show ); };更多信息可参考 usePermissions 文档、DeleteButton文档 与EditButton文档。deleteButtonProps定制删除按钮当资源具有canDelete属性时可以通过deleteButtonProps定制删除按钮的外观与行为。该属性会与组件内部生成的默认 props 合并源码中的展开顺序为{...内置默认, ...deleteButtonPropsFromProps}见 show/index.tsx#L109-L120因此你传入的字段会覆盖默认值。import { Show } from refinedev/mantine; import { usePermissions } from refinedev/core; const PostShow: React.FC () { const { data: permissionsData } usePermissions(); return ( Show canDelete{permissionsData?.includes(admin)} deleteButtonProps{{ size: small }} canEdit{permissionsData?.includes(admin)} pRest of your page here/p /Show ); };值得注意的是默认的删除按钮还内置了onSuccess回调删除成功后自动跳转到该资源的列表页go({ to: goListPath })goListPath由useToPath({ resource, action: list })计算得出。recordItemId在无法从 URL 读取 id 的场景使用Show默认从路由中读取id信息。当组件被用在自定义页面、模态框Modal或抽屉Drawer中无法从 URL 读取 id 时应使用recordItemId显式传入记录 id。典型场景是与useModalForm({ action: show })结合在模态框中展示详情import { Show, useModalForm } from refinedev/mantine; import { Modal, Button } from mantine/core; const PostShow: React.FC () { const { modal: { visible, close, show }, id, } useModalForm({ action: show, }); return ( div Button onClick{() show()}Show Button/Button Modal opened{visible} onClose{close} size{700} withCloseButton{false} Show recordItemId{id} pRest of your page here/p /Show /Modal /div ); };从源码看id的解析优先级为recordItemId ?? idFromParamsshow/index.tsx#L77即显式传入的recordItemId优先于路由参数。同时hasList判断中加入了!recordItemId条件因此传入recordItemId时列表按钮ListButton不会渲染——这一行为在单元测试中也有专门验证见 show/index.spec.tsx#L109-L123。dataProviderName指定数据提供者当应用配置了多个 data provider 时可以通过dataProviderName指定Show内部按钮删除、刷新等使用的 data provider。未指定时使用默认 data provider。import { Refine } from refinedev/core; import { Show } from refinedev/mantine; import dataProvider from refinedev/simple-rest; const PostShow () { return ( Show dataProviderNameother pRest of your page here/p /Show ); }; export const App: React.FC () { return ( Refine dataProvider{{ default: dataProvider(https://api.fake-rest.refine.dev/), other: dataProvider(https://other-api.fake-rest.refine.dev/), }} {/* ... */} /Refine ); };该属性会透传给内部的DeleteButton与RefreshButton见 show/index.tsx#L117、L125。更多关于 data provider 的信息可参考 Data Provider 文档。goBack定制或隐藏返回按钮goBack用于定制返回按钮的内容传入false或null可以隐藏返回按钮。源码中的处理逻辑是goBackFromProps (false || null)时不渲染按钮否则渲染ActionIcon onClick{back}按钮内容为goBackFromProps未传时使用 Mantine 的IconArrowLeft /图标见 show/index.tsx#L139-L148。import { Show } from refinedev/mantine; const PostShow: React.FC () { return ( Show goBack pRest of your page here/p /Show ); };isLoading切换加载状态isLoading用于切换Show组件的加载状态。为true时组件会显示 Mantine 的LoadingOverlay遮罩同时内部按钮会进入disabled状态源码中所有按钮 props 均包含...(isLoading ? { disabled: true } : {})的展开逻辑。import { Show } from refinedev/mantine; const PostShow: React.FC () { return ( Show isLoading{true} pRest of your page here/p /Show ); };类型定义中isLoading的默认值为false见 crud.tsx#L247。breadcrumb定制或禁用面包屑breadcrumb用于定制或禁用面包屑。默认使用refinedev/mantine包中的Breadcrumb组件也可以通过Refine组件的options.breadcrumb做全局配置——源码中组件级breadcrumb未传入时会回退到useRefineContext()读取的全局配置show/index.tsx#L79-L85。import { Show } from refinedev/mantine; const CustomBreadcrumb: React.FC () { return ( p style{{ padding: 3px 6px, border: 2px dashed cornflowerblue, }} My Custom Breadcrumb /p ); }; const PostShow: React.FC () { return ( Show breadcrumb{CustomBreadcrumb /} pRest of your page here/p /Show ); };更多信息可参考 Breadcrumb 文档。单元测试中验证了默认渲染面包屑Posts / Show以及breadcrumb{null}时不渲染面包屑的行为见 show/index.spec.tsx#L605-L667。wrapperProps定制组件外层容器wrapperProps用于定制Show的外层包装元素。在refinedev/mantine中外层包装元素是 Mantine 的Card源码为Card pmd {...wrapperProps}见 show/index.tsx#L169因此wrapperProps可以接收Card支持的全部属性。import { Show } from refinedev/mantine; const PostShow: React.FC () { return ( Show wrapperProps{{ style: { border: 2px dashed cornflowerblue, padding: 16px, }, }} pRest of your page here/p /Show ); };更多信息可参考 Mantine Card 文档。contentProps定制内容区容器contentProps用于定制内容区的包装元素。在 Mantine 实现中内容区为Box ptsm {...contentProps}show/index.tsx#L197因此可接收Box支持的全部属性BoxProps。import { Show } from refinedev/mantine; const PostShow: React.FC () { return ( Show contentProps{{ style: { border: 2px dashed cornflowerblue, padding: 16px, }, }} pRest of your page here/p /Show ); };更多信息可参考 Mantine Box 文档。headerButtons定制头部操作按钮默认情况下Show头部包含ListButton、EditButton、DeleteButton和RefreshButton是否渲染取决于资源配置见 show/index.tsx#L130-L137。headerButtons接受React.ReactNode或渲染函数({ defaultButtons, deleteButtonProps, editButtonProps, listButtonProps, refreshButtonProps }) React.ReactNode可通过渲染函数保留现有按钮并追加自定义按钮import { Show } from refinedev/mantine; import { Button } from mantine/core; const PostShow: React.FC () { return ( Show headerButtons{({ defaultButtons }) ( {defaultButtons} Button variantoutline typeprimary Custom Button /Button / )} pRest of your page here/p /Show ); };或者完全丢弃defaultButtons使用渲染函数提供的各按钮默认 propslistButtonProps、editButtonProps、deleteButtonProps、refreshButtonProps自行组装按钮并在此基础上继续扩展例如追加meta属性import { Show, ListButton, EditButton, DeleteButton, RefreshButton, } from refinedev/mantine; import { Button } from mantine/core; const PostShow: React.FC () { return ( Show headerButtons{({ deleteButtonProps, editButtonProps, listButtonProps, refreshButtonProps, }) ( {listButtonProps ( ListButton {...listButtonProps} meta{{ foo: bar }} / )} {editButtonProps ( EditButton {...editButtonProps} meta{{ foo: bar }} / )} {deleteButtonProps ( DeleteButton {...deleteButtonProps} meta{{ foo: bar }} / )} RefreshButton {...refreshButtonProps} meta{{ foo: bar }} / Button variantoutline typeprimary Custom Button /Button / )} pRest of your page here/p /Show ); };注意listButtonProps等 props 在对应按钮不可见时为undefined例如资源无list路由时因此建议做存在性判断。从源码看headerButtons为函数时参数中的 props 直接来源于组件内部计算出的默认按钮配置show/index.tsx#L150-L160。headerButtonProps定制头部按钮容器headerButtonProps用于定制头部按钮的包装元素。在 Mantine 实现中头部按钮容器为Group spacingxs {...headerButtonProps}show/index.tsx#L193因此可接收Group支持的属性。import { Show } from refinedev/mantine; import { Button } from mantine/core; const PostShow: React.FC () { return ( Show headerButtonProps{{ style: { border: 2px dashed cornflowerblue, padding: 16px, }, }} headerButtons{ Button variantoutline typeprimary Custom Button /Button } pRest of your page here/p /Show ); };更多信息可参考 Mantine Group 文档。footerButtons 与 footerButtonProps定制底部按钮footerButtons用于定制底部按钮区。它同样接受React.ReactNode或渲染函数({ defaultButtons }) React.ReactNode。需要说明的是Show组件默认没有底部按钮——源码中 footer 的默认值为nullfooterButtonsFromProps ? ... : null见 show/index.tsx#L162-L166渲染函数中的defaultButtons为null这与Edit等组件不同。import { Show } from refinedev/mantine; import { Button } from mantine/core; const PostShow: React.FC () { return ( Show footerButtons{({ defaultButtons }) ( {defaultButtons} Button variantgradientCustom Button/Button / )} pRest of your page here/p /Show ); };footerButtonProps用于定制底部按钮容器。Mantine 实现中底部容器为Group positionright spacingxs mtmd {...footerButtonProps}show/index.tsx#L200-L202import { Show } from refinedev/mantine; import { Button } from mantine/core; const PostShow: React.FC () { return ( Show footerButtonProps{{ style: { float: right, marginRight: 24, border: 2px dashed cornflowerblue, padding: 16px, }, }} footerButtons{ Button variantoutline typeprimary Custom Button /Button } pRest of your page here/p /Show ); };更多信息可参考 Mantine Box 文档。源码视角Show的渲染结构与默认行为从 packages/mantine/src/components/crud/show/index.tsx 可以看出Show的最终渲染结构为Card pmd {...wrapperProps} LoadingOverlay visible{loadingOverlayVisible} / // isLoading 遮罩 Group positionapart aligncenter {...headerProps} Stack spacingxs {breadcrumbComponent} // 面包屑 Group spacingxs {buttonBack} // 返回按钮 {title ?? Title order{3}{默认标题}/Title} // 标题 /Group /Stack Group spacingxs {...headerButtonProps} {headerButtons} // 头部按钮组 /Group /Group Box ptsm {...contentProps} {children} // 内容区 /Box Group positionright spacingxs mtmd {...footerButtonProps} {footerButtons} // 底部按钮组 /Group /Card几个值得注意的实现细节标题的国际化与人性化命名默认标题通过translate(${identifier}.titles.show,Show ${getUserFriendlyName(resource?.meta?.label ?? identifier, singular)})生成即优先使用资源 meta 中的label否则使用资源名并转成单数形式例如posts→Show post。删除成功自动回列表默认DeleteButton的onSuccess会调用go({ to: goListPath })跳转到列表页提升操作闭环体验。headerProps已支持但文档未展开从源码看组件还接收headerProps头部行的容器属性作用于Group positionapart在RefineCrudShowProps类型中也有对应定义可作为高级定制入口。组件可 swizzleShow支持通过 Refine CLI 进行 swizzle 定制将其弹出到你的项目中自由修改。测试验证行为有据可依refinedev/mantine为Show提供了完备的单元测试show/index.spec.tsx并复用了 UI 集成共享测试套件crudShowTests来自refinedev/ui-tests覆盖了以下关键行为权限联动配合accessControlProvider的can方法编辑/列表按钮可用删除按钮在无权限时被禁用RefineButtonTestIds.DeleteButton处于 disabled 状态按钮显隐规则资源canDelete: false/canEdit: false时不渲染对应按钮组件上的canDelete/canEditprop 可以覆盖资源配置true覆盖false、false覆盖true传入deleteButtonProps即使资源canDelete: false也会渲染删除按钮——这与源码中isDeleteButtonVisible canDelete ?? (resource?.meta?.canDelete || deleteButtonPropsFromProps)的逻辑完全一致recordItemId 行为传入recordItemId后listButtonProps为undefined、不渲染ListButton但编辑/删除按钮照常渲染面包屑默认渲染 Posts / Show 两级面包屑breadcrumb{null}时面包屑不渲染headerButtons 定制渲染函数可拿到各按钮 props 并自由重组默认按钮。这些测试用例既是对组件行为的规范也是你在自定义headerButtons、canDelete/canEdit时可直接参考的官方用法范例。总结Show组件是 Refine Mantine 应用中构建详情页的布局骨架它本身不关心数据如何获取只负责把标题、面包屑、返回按钮、操作按钮、内容区和加载遮罩有条理地组织起来。实际开发中你只需要用useShow获取记录数据与加载态将加载态传给isLoading并在 children 中渲染字段按需通过title、canDelete/canEdit、deleteButtonProps、headerButtons、footerButtons、breadcrumb等属性定制页面行为与外观在模态框、抽屉或自定义页面等无法从路由读取 id 的场景中用recordItemId显式指定记录 id。掌握这些属性与底层实现即可用最少的代码搭建出专业、可维护的详情展示页面并将它无缝融入 Refine 的资源体系路由、data provider、权限、国际化之中。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考