Refine 与 Mantine 深度集成指南:用 @refinedev/mantine 快速构建内部工具与 Admin 面板
2026/9/13 1:27:49 网站建设 项目流程

Refine 与 Mantine 深度集成指南:用 @refinedev/mantine 快速构建内部工具与 Admin 面板

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

导读

Refine 是一个用于构建内部工具、管理后台、Dashboard 与 B2B 应用的 React 框架。本文基于 Refine v5 官方文档中 Mantine UI 集成章节,系统讲解@refinedev/mantine集成包的安装、表格、表单、通知、预定义组件(布局、按钮、视图、字段、认证页)、主题以及 Inferencer 自动生成等核心能力。读完本文,你将掌握如何在一小时内用 Refine + Mantine v5 搭建一个具备 CRUD、认证、权限控制与主题切换能力的完整管理后台,并理解集成包的底层实现原理。

集成包概览:补充而非替代

Refine 为 Mantine 提供了一整套开箱即用的集成包@refinedev/mantine。它提供了一系列将 Refine 能力与 Mantine 组件桥接的组件与 Hooks:表格状态管理、表单校验与提交、认证流程、通知系统、路由导航、权限校验等,全部以 Mantine 的视觉语言呈现。

需要特别强调的一点是:这个集成包不是 Mantine 的替代品。你可以像在普通 React 应用中一样使用 Mantine 的全部功能(@mantine/core@mantine/hooks@mantine/form等),Refine 集成只是让这些组件与 Refine 的 data provider、auth provider、resources 等机制协同工作。从 packages/mantine/package.json 的依赖声明可以看到,@refinedev/mantine本身就以@mantine/core@mantine/form@mantine/hooks@mantine/notifications@emotion/react@tabler/icons-react为依赖,最终通过 packages/mantine/src/index.tsx 统一导出 components、providers、hooks、theme、definitions、contexts 六大部分:

export * from "./components/index.js"; export * from "./providers/index.js"; export * from "./hooks/index.js"; export * from "./theme/index.js"; export * from "./definitions/index.js"; export * from "./contexts/index.js";

安装:零额外配置

安装@refinedev/mantine及其配套依赖只需要一条命令,无需任何额外配置:

npm install @refinedev/mantine @refinedev/react-table @mantine/core@5 @mantine/hooks@5 @mantine/form@5 @mantine/notifications@5 @emotion/react@11 @tabler/icons-react @tanstack/react-table

版本支持说明:Refine 的 Mantine 集成目前基于Mantine v5。这一点在 packages/mantine/package.json 中有明确佐证——其 peerDependencies 声明了@mantine/core@^5.10.4@mantine/form@^5.10.4@mantine/hooks@^5.10.4@mantine/notifications@^5.10.4,同时要求@refinedev/core@^5.0.0,并支持react@^18.0.0 || ^19.0.0@types/react@^18.0.0 || ^19.0.0。安装时请务必锁定 Mantine 的@5主版本,避免与集成包不兼容。

各依赖的职责划分如下:

依赖包作用
@refinedev/mantineRefine 的 Mantine 集成包,提供组件、Hooks、Provider、主题
@refinedev/react-table基于 RefineuseTable与 TanStack Table 的表格管理方案
@mantine/core@5Mantine 核心 UI 组件库
@mantine/hooks@5Mantine 的 React Hooks 集合
@mantine/form@5Mantine 表单状态与校验库
@mantine/notifications@5Mantine 通知系统
@emotion/react@11Mantine v5 底层依赖的 CSS-in-JS 引擎
@tabler/icons-react图标库(Refine 组件内部大量使用)
@tanstack/react-tableTanStack Table v8,表格列与排序过滤的底层实现

基本用法:包裹 Provider 并组织路由

集成包的使用模式非常固定:先用 Mantine 的<MantineProvider />包裹应用以提供主题,再把 Refine 提供的布局组件(如<ThemedLayout />)包裹在路由外层。以下以 React Router(@refinedev/react-router)为例给出完整的应用骨架(该示例完整代码可见 documentation/docs/ui-integrations/mantine/introduction/previews/usage-react-router-dom.tsx):

import { Refine, Authenticated } from "@refinedev/core"; import { ErrorComponent, ThemedLayout, RefineThemes, useNotificationProvider, AuthPage, } from "@refinedev/mantine"; import { NotificationsProvider } from "@mantine/notifications"; import { MantineProvider, Global } from "@mantine/core"; import dataProvider from "@refinedev/simple-rest"; import routerProvider, { NavigateToResource, } from "@refinedev/react-router"; import { BrowserRouter, Routes, Route, Outlet, Navigate } from "react-router"; const App: React.FC = () => { return ( <BrowserRouter> <MantineProvider theme={RefineThemes.Blue} withNormalizeCSS withGlobalStyles > <Global styles={{ body: { WebkitFontSmoothing: "auto" } }} /> <NotificationsProvider position="top-right"> <Refine notificationProvider={useNotificationProvider} routerProvider={routerProvider} dataProvider={dataProvider("https://api.fake-rest.refine.dev")} authProvider={authProvider} resources={[ { name: "products", list: "/products", show: "/products/:id", edit: "/products/:id/edit", create: "/products/create", meta: { canDelete: true }, }, ]} > <Routes> <Route element={ <Authenticated fallback={<Navigate to="/login" />}> <Outlet /> </Authenticated> } > <Route element={ <ThemedLayout> <Outlet /> </ThemedLayout> } > <Route index element={<NavigateToResource resource="products" />} /> <Route path="/products" element={<Outlet />}> <Route index element={<ProductList />} /> <Route path="create" element={<ProductCreate />} /> <Route path=":id" element={<ProductShow />} /> <Route path=":id/edit" element={<ProductEdit />} /> </Route> <Route path="*" element={<ErrorComponent />} /> </Route> </Route> {/* 登录、注册等认证路由 */} <Route path="/login" element={<AuthPage type="login" />} /> </Routes> </Refine> </NotificationsProvider> </MantineProvider> </BrowserRouter> ); };

这里有几个值得注意的编排细节:

  • <Authenticated />守卫:通过fallback属性把未认证用户重定向到登录页;认证路由组内则用NavigateToResource把已登录用户引导到资源首页。
  • <ThemedLayout />包裹受保护路由:布局、侧边导航、头部只在登录后渲染。
  • resources声明list/show/edit/create映射了每个操作对应的路由路径,Refine 的按钮、面包屑、菜单会自动依据这份声明生成导航。
  • meta.canDelete:开启后列表视图会渲染删除按钮并启用确认对话框与撤销(undoable)通知。

如果你使用Next.jsRemix,模式完全相同,只是路由部分换成各自的路由方案(@refinedev/nextjs-router@refinedev/remix-router),仓库中分别提供了对应的使用示例,见 documentation/docs/ui-integrations/mantine/introduction/previews/usage-next-js.tsx 与 documentation/docs/ui-integrations/mantine/introduction/previews/usage-remix.tsx。

表格:@refinedev/react-table 驱动的数据列表

Mantine 自带风格化的 Table 原语 与 TanStack Table v8 的useTable之上,把两种表格能力合二为一。Refine 的 Mantine 文档与示例默认使用该包做表格管理,但你完全可以替换成任何其他表格管理方案。

下面是一个完整的产品列表页(含操作列与分页):

import React from "react"; import { useTable } from "@refinedev/react-table"; import { ColumnDef, flexRender } from "@tanstack/react-table"; import { List, ShowButton, EditButton, DeleteButton } from "@refinedev/mantine"; import { Box, Group, ScrollArea, Table, Pagination } from "@mantine/core"; const columns = [ { id: "id", header: "ID", accessorKey: "id" }, { id: "name", header: "Name", accessorKey: "name", meta: { filterOperator: "contains" }, }, { id: "price", header: "Price", accessorKey: "price" }, { id: "actions", header: "Actions", accessorKey: "id", enableColumnFilter: false, enableSorting: false, cell: function render({ getValue }) { return ( <Group spacing="xs" noWrap> <ShowButton hideText recordItemId={getValue() as number} /> <EditButton hideText recordItemId={getValue() as number} /> <DeleteButton hideText recordItemId={getValue() as number} /> </Group> ); }, }, ]; export const ProductList = () => { const { reactTable: { getHeaderGroups, getRowModel }, refineCore: { setCurrentPage, pageCount, currentPage, tableQuery: { data: tableData }, }, } = useTable<IProduct>({ columns }); return ( <ScrollArea> <List> <Table highlightOnHover> <thead> {getHeaderGroups().map((headerGroup) => ( <tr key={headerGroup.id}> {headerGroup.headers.map((header) => ( <th key={header.id}> {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> <br /> <Pagination position="right" total={pageCount} page={currentPage} onChange={setCurrentPage} /> </List> </ScrollArea> ); };

理解这个返回结构是掌握@refinedev/react-table的关键:

  • reactTable命名空间:透出 TanStack Table 的全部能力(getHeaderGroupsgetRowModelsetOptions等),因此列定义、过滤、排序、虚拟化等生态工具都能直接使用。
  • refineCore命名空间:透出 Refine 核心useTable的能力(currentPagepageCountsetCurrentPagetableQuery等),分页状态与 data provider 的查询天然联动。
  • 列上的meta.filterOperator:声明该列使用的过滤操作符(如contains),供过滤表单生成对应的查询参数。
  • enableColumnFilter/enableSorting:按列关闭过滤或排序,常用于操作列。

排序与过滤同样可以直接挂在refineCoreProps上,例如设置初始排序:

const { ... } = useTable({ columns, refineCoreProps: { sorters: { initial: [{ field: "id", order: "desc" }], }, }, });

仓库中提供了大量可运行的表格示例:@refinedev/react-table集成包的源码位于 packages/react-table,完整示例项目见 examples/table-mantine-basic 与 examples/table-mantine-advanced,对应的端到端测试在 cypress/e2e/table-mantine-basic 与 cypress/e2e/table-mantine-advanced。

表单:useForm 与表单生态

Refine 与@mantine/formuseForm完成。它内部桥接 Refine 核心的数据操作(create/update)与 Mantine 的表单状态管理。

以下是一个创建产品页(Create 视图):

import { Create, useForm } from "@refinedev/mantine"; import { TextInput, NumberInput } from "@mantine/core"; export const ProductCreate = () => { const { saveButtonProps, getInputProps, errors } = useForm({ initialValues: { name: "", material: "", price: 0, }, }); return ( <Create saveButtonProps={saveButtonProps}> <form> <TextInput mt={8} id="name" label="Name" placeholder="Name" {...getInputProps("name")} /> <TextInput mt={8} id="material" label="Material" placeholder="Material" {...getInputProps("material")} /> <NumberInput mt={8} id="price" label="Price" placeholder="Price" {...getInputProps("price")} /> </form> </Create> ); };

useForm返回值的用法要点:

  • saveButtonProps:直接透传给<Create />(或<Edit />)的保存按钮,点击后触发对应的 create/update mutation,并自动处理加载态、成功/失败通知与数据失效(invalidation)。
  • getInputProps(field):Mantine 表单的标准接线方式,把字段值、变更回调、校验错误绑定到TextInputNumberInput等组件上。
  • errors:服务端返回的表单校验错误映射,可用于展示(配合@mantine/form的校验机制)。
  • 编辑场景useForm会根据当前路由中的资源 id 自动回填数据;还可以开启自动保存,从refineCore中取出autoSaveProps传入<Edit autoSaveProps={autoSaveProps}>
const { saveButtonProps, getInputProps, errors, refineCore: { query, autoSaveProps } } = useForm({ initialValues: { name: "", material: "", price: 0 }, refineCoreProps: { autoSave: { enabled: true }, }, });

除基础useForm外,集成包还针对不同交互形态提供了专门 Hooks:

Hook适用场景文档
useModalForm在弹窗(Modal)内完成创建/编辑use-modal-form
useDrawerForm在抽屉(Drawer)内完成创建/编辑use-drawer-form
useStepsForm分步表单(多步骤向导)use-steps-form
useSelect关联数据下拉选择(如外键字段)use-select

其中useSelect复用了@refinedev/coreuseSelect,能基于资源的 data provider 自动拉取选项列表并映射label/value,非常适合实现"选择某个分类/用户"这类关系型字段,还内置了搜索(onSearch)与排序支持。

仓库中对应的可运行示例包括 examples/form-mantine-use-form、examples/form-mantine-use-modal-form、examples/form-mantine-use-drawer-form、examples/form-mantine-use-steps-form,以及校验相关示例 examples/form-mantine-mutation-mode 与 examples/server-side-form-validation-mantine,对应的 Cypress 测试位于 cypress/e2e/form-mantine-use-form 等目录。

通知:无缝接入 Mantine Notifications

Mantine 自带内置通知系统@mantine/notifications,与自身 UI 元素配合默契。Refine 通过useNotificationProvider把 Refine 的动作/事件通知(成功、错误、进度)桥接到 Mantine 的通知系统上,直接赋值给<Refine />notificationProvider属性即可:

import { Refine } from "@refinedev/core"; import { useNotificationProvider } from "@refinedev/mantine"; import { NotificationsProvider } from "@mantine/notifications"; const App = () => { return ( // `@mantine/notifications` 也需要一个 context provider 才能工作 <NotificationsProvider position="top-right"> <Refine notificationProvider={useNotificationProvider}> {/* ... */} </Refine> </NotificationsProvider> ); };

从源码 packages/mantine/src/providers/notificationProvider.tsx 可以看到其底层实现逻辑:

  • open方法区分两种通知类型:
    • type === "progress":渲染一个带倒计时圆环(RingCountdown,实现见 packages/mantine/src/components/ring-countdown/index.tsx)的进度通知,配合undoableTimeout展示"可撤销"倒计时,并提供撤销按钮(IconRotate2),点击后调用cancelMutation?.()取消变更。这正是 DeleteButton 等破坏性操作支持撤销机制的来源。
    • 成功/失败通知:成功用IconCheck+ 主色,失败用IconX+ 红色,默认autoClose: 5000(5 秒自动关闭),description作为标题展示。
  • close(key):根据通知 key 移除并隐藏对应通知。
  • 实现内部维护activeNotifications数组,通过addNotification/removeNotification/isNotificationActive实现按 key 的去重更新(先showNotification,后续用updateNotification原地更新)。
  • 源码同时保留了旧导出notificationProvideruseNotificationProvider的别名),并标记为 deprecated,统一使用useNotificationProvider命名。

预定义组件与视图

布局、菜单与面包屑

Refine 提供基于 Mantine 组件打造的布局组件,内置了导航菜单、头部、认证与授权等 Refine 特性。其实现位于 packages/mantine/src/components/themedLayout/index.tsx,内部由 Sider、Header、HamburgerMenu、Title 等子组件组成。

<ThemedLayout />由三部分组成:

  • Sider(侧边栏):根据<Refine />resources声明自动生成导航菜单项;如果配置了 auth provider,还会显示登出按钮。
  • Header(头部):展示应用 logo 与名称;如果配置了 auth provider,还会显示当前用户信息。
  • 内容区:渲染children(即当前路由页面)。

三种框架下的布局写法分别见 layout-react-router-dom.tsx、layout-next-js.tsx 与 layout-remix.tsx。

此外,<Breadcrumb />组件以 Mantine 组件为基底,根据当前路由自动生成合适的面包屑导航,并默认嵌入在 Refine 提供的基础视图中。

按钮

Mantine 集成包提供了多种建立在 Mantine<Button />之上的业务按钮,内置了大量逻辑功能:

  • 授权检查(根据 access control provider 决定显隐/禁用)
  • 确认对话框(如删除确认)
  • 加载状态(mutation 进行中显示 loading)
  • 数据失效(操作完成后刷新相关查询)
  • 导航(跳转到对应资源路由)
  • 表单动作(提交保存)
  • 导入/导出

例如<EditButton />在列表操作列中的用法:

import React from "react"; import { useTable } from "@refinedev/react-table"; import { ColumnDef, flexRender } from "@tanstack/react-table"; import { List, EditButton } from "@refinedev/mantine"; const columns = [ { id: "id", header: "ID", accessorKey: "id" }, { id: "name", header: "Name", accessorKey: "name", meta: { filterOperator: "contains" } }, { id: "price", header: "Price", accessorKey: "price" }, { id: "actions", header: "Actions", accessorKey: "id", cell: function render({ getValue }) { return <EditButton hideText recordItemId={getValue() as number} />; }, }, ]; export const ProductList = () => { const table = useTable({ columns }); return ( /* ... */ ); };

recordItemId指定按钮操作的目标记录,hideText只显示图标。完整按钮清单如下,每个按钮的源码与单元测试位于 packages/mantine/src/components/buttons:

  • <CreateButton />
  • <EditButton />
  • <ListButton />
  • <ShowButton />
  • <CloneButton />
  • <DeleteButton />
  • <SaveButton />
  • <RefreshButton />
  • <ImportButton />
  • <ExportButton />

这些按钮大多已内置于 Refine 提供的基础视图中——使用<List /><Show /><Edit /><Create />时,合适的按钮会自动出现在正确位置,无需手工拼装。

视图

视图(Views)是页面内容的包装器,设计为在布局内使用,提供基于资源的标题、面包屑、相关操作与授权检查。它们基于 Mantine 的<Box />

  • <List />
  • <Show />
  • <Edit />
  • <Create />

字段组件

字段(Fields)组件用于以 Mantine 的恰当设计与格式渲染值,构建在对应 Mantine 组件之上,并附带值的格式化逻辑。它们可以组合或扩展以满足定制需求。字段组件源码位于 packages/mantine/src/components/fields:

  • <BooleanField />
  • <DateField />
  • <EmailField />
  • <FileField />
  • <MarkdownField />
  • <NumberField />
  • <TagField />
  • <TextField />
  • <UrlField />

详情页展示示例:

import { useShow } from "@refinedev/core"; import { Show, TextField, NumberField, MarkdownField } from "@refinedev/mantine"; import { Title } from "@mantine/core"; export const ProductShow = () => { const { result: product, query } = useShow(); const { data, isLoading } = query; return ( <Show isLoading={isLoading}> <Title mt="xs" order={5}>Name</Title> <TextField value={product?.name} /> <Title mt="xs" order={5}>Description</Title> <MarkdownField value={product?.description} /> <Title mt="xs" order={5}>Price</Title> <NumberField value={product?.price} options={{ style: "currency", currency: "USD" }} /> </Show> ); };

注意NumberFieldoptions直接透传给Intl.NumberFormat,因此可以像这里一样用style: "currency", currency: "USD"输出本地化的货币格式;MarkdownField内部基于react-markdown+remark-gfm渲染 Markdown 内容(相关依赖见 packages/mantine/package.json)。

认证页面

认证页面(Auth Pages)专门用于应用认证流程,通过复用 Refine 的认证 Hooks,提供开箱即用的登录、注册、忘记密码与重置密码页面。它们构建在 Mantine 基础组件(如<TextInput /><Card />)之上,实现位于 packages/mantine/src/components/pages/auth。可用类型:

  • <AuthPage type="login" />
  • <AuthPage type="register" />
  • <AuthPage type="forgot-password" />
  • <AuthPage type="reset-password" />

用法参见 documentation/docs/ui-integrations/mantine/components/auth-page/index.md。在 App.tsx 中它通常与Authenticated守卫配合,例如传入formProps预填演示账号:

<AuthPage type="login" formProps={{ initialValues: { email: "demo@refine.dev", password: "demodemo", }, }} />

错误组件

集成包还提供<ErrorComponent />用于渲染 404 页面。它不提供太多功能,但能保证错误页与整体设计语言一致:

import { ErrorComponent } from "@refinedev/mantine"; const NotFoundPage = () => { return <ErrorComponent />; };

主题:开箱即用的 RefineThemes 与深浅色支持

Refine 提供了应用级组件(布局、侧边栏、头部)和页面级组件,因此与 Mantine 样式的协同至关重要。@refinedev/mantine导出的所有组件与 Provider 都会自动跟随 Mantine 的当前主题,无需额外配置。

同时,Refine 提供了一套精心设计的 Mantine 主题,输出与 Refine 组件搭配良好的 UI,支持亮色与暗色模式。主题以RefineThemes对象形式从@refinedev/mantine导出,直接传入<MantineProvider theme={...}>即可:

import { MantineProvider } from "@mantine/core"; import { RefineThemes } from "@refinedev/mantine"; <MantineProvider theme={RefineThemes.Blue} withNormalizeCSS withGlobalStyles>

从源码 packages/mantine/src/theme/index.ts 可以看到主题系统的完整实现:

  • 内置 7 套品牌色BluePurpleMagentaRedOrangeYellowGreen,每套都是一组 10 档的 Mantine 色阶(如 Blue 从#E7F5FF#1864AB),统一映射到brand主色并设置为primaryColor
  • 全局背景联动:每套主题都注入globalStyles,根据theme.colorScheme自动切换body背景色(暗色用dark[8],亮色用gray[0]),因此切换主题即切换深浅色背景。
  • 默认主题细节commonThemeProperties定义了 Montserrat 字体栈、defaultRadius: 6、以及Table组件的表头/表行样式定制(表头灰底、圆角,行底部分隔线),确保 Refine 组件观感统一。
  • 仓库还单独导出了LightThemeDarkTheme(基于一套绿色系primary色阶),可用作无品牌色的基础主题。

若需要更深入的主题定制(颜色、字体、圆角、组件样式),可参考 Mantine 官方主题对象文档 与主题演示示例 examples/theme-mantine-demo。

Inferencer:用 AI 生成视图代码

@refinedev/inferencer可以根据你的 data provider 数据结构,自动生成资源的列表、详情、编辑、创建视图。它从@refinedev/mantine集成导出以下组件:

  • MantineListInferencer:自动生成列表页
  • MantineShowInferencer:自动生成详情页
  • MantineEditInferencer:自动生成编辑页
  • MantineCreateInferencer:自动生成创建页
  • MantineInferencer:四者合一的组合组件

典型用法是把<MantineInferencer />挂到某个资源路由上,让 Refine 自动生成并渲染对应视图;生成后的代码可直接复制到项目中作为起点继续开发。更完整的说明见 Mantine Inferencer 文档,Inferencer 的 Mantine 渲染实现位于 packages/inferencer/src/inference-resolvers(对应mantine解析器),配套示例项目见 examples/inferencer-mantine。

小结与快速上手路径

从本文可以总结出@refinedev/mantine的完整使用路径:

  1. 安装:一次性安装@refinedev/mantine及其依赖,注意锁定 Mantine@5
  2. 组织应用MantineProvider(主题)→NotificationsProvider(通知)→<Refine />(providers + resources)→ 路由与ThemedLayout
  3. 按需取用:表格用@refinedev/react-tableuseTable;表单用useForm/useModalForm/useDrawerForm/useStepsForm;关联字段用useSelect;展示用 Fields;操作与导航用 Buttons;页面骨架用 Views 与 AuthPage。
  4. 提升效率:用RefineThemes一键获得品牌化主题与深浅色支持;用 Inferencer 自动生成视图代码再人工打磨。

如果想直接运行一个完整可用的示例,仓库中的 examples/form-mantine-use-form、examples/table-mantine-advanced、examples/auth-mantine 以及 examples/base-mantine 都是很好的起点,每个示例都包含package.json与完整的src目录,可直接安装依赖后启动。

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询