Refine 教程实战:结合 Material UI 与 React Router 搭建带主题布局的 CRUD 应用

发布时间:2026/9/13 16:02:50

Refine 教程实战:结合 Material UI 与 React Router 搭建带主题布局的 CRUD 应用 Refine 教程实战结合 Material UI 与 React Router 搭建带主题布局的 CRUD 应用【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本篇基于 Refine 官方教程中的 Material UI 章节讲解如何在一个已完成路由集成的 Refine 项目中引入 Material UI安装refinedev/mui及相关 MUI 依赖、使用RefineThemes预置主题包裹应用、挂载CssBaseline与GlobalStyles重置浏览器默认样式并用ThemedLayout /一步获得侧边栏与头部布局。读完本文你将掌握 Refine MUI 集成的主题体系与布局组件的工作原理并能对照仓库源码理解每个组件背后的实现。本单元的定位与整体目标该章节位于教程「UI Libraries」部分的 Material UI 子线教程原文承接前一单元「Refine 的路由集成」目标是基于refinedev/react-router与 Material UI 共同构建一个完整的 CRUD 应用。Refine 为 Material UI、Ant Design、Chakra UI 和 Mantine 等主流 UI 库提供官方集成这些集成提供了一组组件与 Hooks简化表单与表格管理、布局、视图、按钮等开发工作官方文档详见 Material UI 集成文档目录。本单元覆盖的主题包括使用布局组件为应用添加菜单、头部、面包屑和认证管理使用 CRUD 视图组件创建设计一致、功能统一的动作页面使用 Hooks 将表单元素和表格与 Refine 的useTable、useForm集成使用notistack将 Refine 的通知系统与 Material UI 的通知能力打通使用AuthPage /组件管理认证页面。注意Material UI 自带表单元素但不提供表单状态管理方案。教程后续会引入 Refine 的 React Hook Form 集成包refinedev/react-hook-form基于 RefineuseFormHook 的扩展来管理表单状态其安装会在重构表单组件的步骤中进行。添加 Material UI 依赖要使用 Material UI 组件并访问 Refine 的集成 Hooks 与组件需要安装refinedev/mui包。完整依赖如下npm install refinedev/mui emotion/react emotion/styled mui/lab mui/material mui/x-data-grid其中emotion/react与emotion/styled是 MUI 的样式引擎mui/material是核心组件库mui/lab提供实验性组件如Autocomplete的异步加载模式mui/x-data-grid则用于 Refine 表格集成。教程的 Sandpack 沙箱配置 中锁定了实际使用的版本组合mui/material为 6.x、mui/x-data-grid为 7.x、refinedev/mui取 latest可作为实操时的版本参考。用 ThemeProvider 挂载主题与全局样式重置应用需要用 MUI 的ThemeProvider /包裹来设定主题并挂载CssBaseline /与GlobalStyles /重置浏览器的默认样式。ThemeProvider /需要传入themepropRefine 提供了预置主题RefineThemes覆盖多种色彩方案与暗色模式可以直接用于加速开发并保持应用设计一致。按教程更新src/App.tsximport { Refine, Authenticated } from refinedev/core; import routerProvider, { NavigateToResource } from refinedev/react-router; import { BrowserRouter, Routes, Route, Outlet } from react-router; // highlight-next-line import { RefineThemes } from refinedev/mui; // highlight-start import CssBaseline from mui/material/CssBaseline; import GlobalStyles from mui/material/GlobalStyles; import { ThemeProvider } from mui/material/styles; // highlight-end import { dataProvider } from ./providers/data-provider; import { authProvider } from ./providers/auth-provider; import { ShowProduct } from ./pages/products/show; import { EditProduct } from ./pages/products/edit; import { ListProducts } from ./pages/products/list; import { CreateProduct } from ./pages/products/create; import { Login } from ./pages/login; import { Header } from ./components/header; export default function App(): JSX.Element { return ( BrowserRouter {/* highlight-start */} {/* Were using Refines Blue theme here. You can use other variants or create your own theme without constraints. */} ThemeProvider theme{RefineThemes.Blue} CssBaseline / GlobalStyles styles{{ html: { WebkitFontSmoothing: auto } }} / {/* highlight-end */} Refine dataProvider{dataProvider} authProvider{authProvider} routerProvider{routerProvider} resources{[ { name: protected-products, list: /products, show: /products/:id, edit: /products/:id/edit, create: /products/create, meta: { label: Products }, }, ]} Routes Route element{ Authenticated keyauthenticated-routes redirectOnFail/login Header / Outlet / /Authenticated } Route index element{NavigateToResource resourceprotected-products /} / Route path/products Route index element{ListProducts /} / Route path:id element{ShowProduct /} / Route path:id/edit element{EditProduct /} / Route pathcreate element{CreateProduct /} / /Route /Route Route element{ Authenticated keyauth-pages fallback{Outlet /} NavigateToResource resourceprotected-products / /Authenticated } Route path/login element{Login /} / /Route /Routes /Refine {/* highlight-start */} /ThemeProvider {/* highlight-end */} /BrowserRouter ); }从源码看 RefineThemes 的生成机制RefineThemes并非手工逐个编写而是在 packages/mui/src/theme/index.ts 中由色板表程序化生成const RefineThemes Object.keys(RefinePalettes).reduce((acc, key) { const paletteName key as keyof typeof RefinePalettes; return { ...acc, [key]: createTheme({ palette: { ...RefinePalettes[paletteName] }, components: { MuiButton: { styleOverrides: { root: ({ ownerState }) ({ ...(ownerState.variant contained ownerState.color primary { color: #fff, }), }), }, }, }, }), }; }, {}) as Recordkeyof typeof RefinePalettes, Theme;色板定义在 packages/mui/src/theme/palette/refinePalette.ts共 6 组色彩每组各提供浅色与深色两个变体合计 12 个主题主题模式primary.mainBlue/BlueDarklight / dark#1976D2/#67b7f7Purple/PurpleDarklight / dark#7B1FA2/#AB47BCMagenta/MagentaDarklight / dark#C2185B/#EC407ARed/RedDarklight / dark#D32F2F/#EF5350Orange/OrangeDarklight / dark#F57C00/#FFA726Yellow/YellowDarklight / dark#FFA000/#FFCA28Green/GreenDarklight / dark#689F38/#9CCC65同文件还额外导出了两个完整的LightTheme与DarkTheme二者共享shape.borderRadius: 6与统一的typography分别使用 lightPalette 与 darkPalette 定义完整调色板并对MuiAppBar、MuiPaper、MuiTypography做了针对性覆盖例如浅色主题中 AppBar 背景设为白色、h5标题加粗至 800。从源码结构看如果你的应用需要比RefineThemes更完整的光暗双模式可以改用LightTheme/DarkTheme并自行调整palette。用 ThemedLayout 挂载布局教程的下一步是用 Refine 提供的ThemedLayout /包裹受认证保护的根路由它自带侧边栏、头部、面包屑等开箱即用能力。更新后的src/App.tsx相对上一步的增量是把Header /替换为ThemedLayoutimport { Refine, Authenticated } from refinedev/core; import routerProvider, { NavigateToResource } from refinedev/react-router; import { BrowserRouter, Routes, Route, Outlet } from react-router; // highlight-next-line import { RefineThemes, ThemedLayout } from refinedev/mui; import CssBaseline from mui/material/CssBaseline; import GlobalStyles from mui/material/GlobalStyles; import { ThemeProvider } from mui/material/styles; import { dataProvider } from ./providers/data-provider; import { authProvider } from ./providers/auth-provider; import { ShowProduct } from ./pages/products/show; import { EditProduct } from ./pages/products/edit; import { ListProducts } from ./pages/products/list; import { CreateProduct } from ./pages/products/create; import { Login } from ./pages/login; export default function App(): JSX.Element { return ( BrowserRouter ThemeProvider theme{RefineThemes.Blue} CssBaseline / GlobalStyles styles{{ html: { WebkitFontSmoothing: auto } }} / Refine dataProvider{dataProvider} authProvider{authProvider} routerProvider{routerProvider} resources{[ { name: protected-products, list: /products, show: /products/:id, edit: /products/:id/edit, create: /products/create, meta: { label: Products }, }, ]} Routes Route element{ Authenticated keyauthenticated-routes redirectOnFail/login {/* highlight-start */} ThemedLayout Outlet / /ThemedLayout {/* highlight-end */} /Authenticated } Route index element{NavigateToResource resourceprotected-products /} / Route path/products Route index element{ListProducts /} / Route path:id element{ShowProduct /} / Route path:id/edit element{EditProduct /} / Route pathcreate element{CreateProduct /} / /Route /Route Route element{ Authenticated keyauth-pages fallback{Outlet /} NavigateToResource resourceprotected-products / /Authenticated } Route path/login element{Login /} / /Route /Routes /Refine /ThemeProvider /BrowserRouter ); }至此应用就被一个带侧边栏和头部的完整布局包裹了。ThemedLayout 的源码结构从 packages/mui/src/components/themedLayout/index.tsx 的实现看ThemedLayout接受以下关键 propsProp说明Sider/Header/Title/Footer自定义布局区块不传时使用内置的ThemedSider、ThemedHeader等默认实现OffLayoutArea渲染在 Sider 与主区域之外的附加区域通常用于UnsavedChangesNotifier等全局弹层initialSiderCollapsed/onSiderCollapsed侧边栏初始折叠状态与折叠状态回调childrenBoxProps/containerBoxProps传给内容容器与外层容器的BoxProps含sx用于微调间距、背景等其内部渲染结构为ThemedLayoutContextProvider提供侧边栏折叠状态的上下文外层是一个横向 Flex 容器Sider 固定在左侧右侧纵向排列Header、内容main响应式内边距p: { xs: 1, md: 2, lg: 3 }背景取自theme.palette.background.default以及可选的FooterOffLayoutArea挂在最外层 Flex 容器末尾。侧边栏与头部的拆分实现在 sider、header 子目录中配套的HamburgerMenu、ThemedTitle也一并导出见 components/index.tsx后续步骤会逐一展开这些布局特性。refinedev/mui 的完整能力面依赖装好、主题与布局就位后这个包实际提供的能力可以从其入口 packages/mui/src/index.tsx 与 packages/mui/src/components/index.tsx 看到全貌与本单元后续主题一一对应布局组件ThemedLayout、ThemedSider、ThemedTitle、ThemedHeader、HamburgerMenu认证页面components/pages/auth下的Login、Register、ForgotPassword、UpdatePassword及统一导出的AuthPage /对应主题列表中的第 5 项CRUD 视图CreateView、EditView、ListView、ShowView等保证四个动作页设计与交互一致按钮组件CreateButton、EditButton、DeleteButton、ShowButton、ListButton、RefreshButton、SaveButton、ImportButton、ExportButton、CloneButton以及面包屑Breadcrumb表单字段BooleanInput、DateInput、EmailInput、FileInput、MarkdownInput、NumberInput、TextInput、TagInput、UrlInput等通知集成RefineSnackbarProvider、useNotificationProvider并直接转出notistack的SnackbarProvider、useSnackbar等 APIHooksuseAutocomplete、useDataGrid、useThemedLayoutContext见 packages/mui/src/hooks/index.ts。参考仓库中的完整示例examples/tutorial-material-ui仓库内 examples/tutorial-material-ui 是该教程线的可运行落地版本其 src/App.tsx 展示了本单元各步骤完成后的「完整形态」——在本章代码基础上进一步加入通知与体验组件BrowserRouter GitHubBanner / ThemeProvider theme{RefineThemes.Blue} CssBaseline / GlobalStyles styles{{ html: { WebkitFontSmoothing: auto } }} / RefineSnackbarProvider Refine routerProvider{routerProvider} dataProvider{dataProvider(https://api.fake-rest.refine.dev)} notificationProvider{useNotificationProvider} resources{[{ name: blog_posts, /* ... */ }]} options{{ syncWithLocation: true, warnWhenUnsavedChanges: true }} ThemedLayout Routes {/* ... index 与 /blog-posts 下的 list/show/create/edit 路由 ... */} Route path* element{ErrorComponent /} / /Routes /ThemedLayout UnsavedChangesNotifier / DocumentTitleHandler / /Refine /RefineSnackbarProvider /ThemeProvider /BrowserRouter相比教程本章它额外演示了三点一是RefineSnackbarProvider包裹Refine并注入useNotificationProvider作为notificationProvider这正是主题列表中「使用 notistack 集成通知」的落地方式二是UnsavedChangesNotifier与options.warnWhenUnsavedChanges: true配合防止表单未保存时误跳转三是使用ErrorComponent兜底未匹配路由。该示例使用refinedev/simple-rest对接api.fake-rest.refine.dev无需后端即可跑通适合作为本文步骤完成后的验证参照。小结本章完成了 Material UI 集成的两块基石依赖与主题安装refinedev/mui与 MUI 全家桶用ThemeProvider theme{RefineThemes.Blue}挂载预置主题并配合CssBaseline、GlobalStyles完成样式基线RefineThemes的 12 个色板主题由源码中的RefinePalettes程序化生成另有LightTheme/DarkTheme可用于完整光暗模式场景。布局用ThemedLayout /包裹受认证保护的路由出口一步获得侧边栏、头部与面包屑能力其Sider/Header/Footer/OffLayoutArea等 props 与ThemedLayoutContext为后续深度定制留出了扩展点。后续步骤将依次深入布局组件的菜单/认证区细节、ListView/CreateView等 CRUD 视图、基于useTable与useForm的表格与表单集成、notistack通知接线以及AuthPage /认证页面的使用。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/13 16:02:50

RAG系统安全基准测试:核心挑战与实战方案

1. RAG安全基准测试的必要性与核心挑战 检索增强生成(Retrieval-Augmented Generation,简称RAG)系统已成为当前AI应用的主流架构之一。但我在实际企业级部署中发现,许多团队在系统上线前往往忽视安全性和性能的量化评估&#xff0…

2026/9/13 16:52:54

Stable Diffusion WebUI Forge:一键上手AI图像生成的完整指南

Stable Diffusion WebUI Forge:一键上手AI图像生成的完整指南 【免费下载链接】stable-diffusion-webui-forge 项目地址: https://gitcode.com/GitHub_Trending/st/stable-diffusion-webui-forge 想把一张草图变成概念图时,需要的不是再装一堆插…

2026/9/13 16:52:54

Java Servlet+JDBC健身房会员管理系统实战解析

简介:本资源是一套完整的健身房会员管理系统设计源码,面向计算机专业本科生、Web开发初学者及中小型健身场馆信息化建设需求者,解决会员信息管理、课程预约、教练分配与财务统计等核心运营问题。压缩包共187个文件,含65个Java后端…

2026/9/13 16:47:53

基于STK11的卫星任务调度强化学习数据生成与训练实践

简介:基于STK11场景的卫星任务调度与强化学习训练数据生成系统,面向卫星任务规划与机器学习交叉领域的研究者或工程师,提供从随机观测任务生成、卫星可访问时段计算、数据对齐与批次排序,到数据增强、模型训练及奖励可视化的完整链…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码