React Router Dom v6根据参数渲染路由组件的优化方案咨询
React 18后台管理系统路由优化方案
问题背景
基于React 18开发后台管理系统,使用React Router Dom v6实现路由。管理员登录后跳转至/admin,通过Ant Design侧边菜单同步路由,当前用switch结合useParams的:page参数在AdminView中选择渲染组件,功能可行但不够优雅,需要更简洁的实现方案。
当前核心代码如下:
主路由配置
<Route path="/admin"> <Route path="login" element={<AdminLogin />} /> <Route path=":page" element={<AdminView />} /> </Route>
AdminView组件选择逻辑
const getTable = () => { switch (table) { case 'realms': return RealmsTable; case 'clients': return ClientsTable; case 'users': return UsersTable; case 'roles': return RolesTable; case 'management': return Management; default: return NotFoundtView; } }; const Table = useMemo(getTable, [table]);
侧边菜单同步路由
const { table } = useParams(); return ( <Sider> <Menu className="no-bg" items={items} onClick={onMenuSelect} mode="inline" defaultSelectedKeys={[table!]} inlineCollapsed={collapsed} theme="dark" ></Menu> </Sider> );
优化方案
方案一:组件映射表替代Switch语句
用对象映射替代switch,代码更简洁,新增页面仅需在映射表中添加键值对,维护成本更低。
// 定义组件映射表,集中管理页面与组件的对应关系 const pageComponentMap = { realms: RealmsTable, clients: ClientsTable, users: UsersTable, roles: RolesTable, management: Management, }; // 在AdminView中直接通过映射表获取组件 const Table = useMemo(() => { return pageComponentMap[table] || NotFoundtView; }, [table]);
方案二:利用React Router v6嵌套子路由直接渲染组件
放弃通过:page参数分发组件的方式,直接将各页面作为/admin的子路由,让React Router自动处理组件渲染,更符合路由设计理念。
修改路由配置
<Route path="/admin"> <Route path="login" element={<AdminLogin />} /> {/* 每个页面作为独立子路由 */} <Route path="realms" element={<RealmsTable />} /> <Route path="clients" element={<ClientsTable />} /> <Route path="users" element={<UsersTable />} /> <Route path="roles" element={<RolesTable />} /> <Route path="management" element={<Management />} /> {/* 匹配/admin下未定义的路径,返回404 */} <Route path="*" element={<NotFoundtView />} /> </Route>
修改侧边菜单同步逻辑
import { useLocation, useNavigate } from 'react-router-dom'; const location = useLocation(); const navigate = useNavigate(); // 从当前路径提取最后一段作为选中菜单的key const currentPage = location.pathname.split('/').pop() || ''; // 菜单点击跳转逻辑 const onMenuSelect = ({ key }) => { navigate(`/admin/${key}`); }; return ( <Sider> <Menu className="no-bg" items={items} onClick={onMenuSelect} mode="inline" selectedKeys={[currentPage]} // 直接用当前路径片段设置选中项 inlineCollapsed={collapsed} theme="dark" ></Menu> </Sider> );
方案三:统一配置路由与侧边菜单
将路由规则和菜单配置合并到一个数组中,新增页面仅需修改一处配置,避免路由与菜单不同步的问题,大幅降低维护成本。
1. 创建统一配置文件(如src/config/adminRoutes.js)
import RealmsTable from '../components/RealmsTable'; import ClientsTable from '../components/ClientsTable'; import UsersTable from '../components/UsersTable'; import RolesTable from '../components/RolesTable'; import Management from '../components/Management'; export const adminRoutes = [ { key: 'realms', path: 'realms', element: <RealmsTable />, label: '领域管理', // 菜单显示文本 // 可添加icon等其他菜单属性 }, { key: 'clients', path: 'clients', element: <ClientsTable />, label: '客户端管理', }, { key: 'users', path: 'users', element: <UsersTable />, label: '用户管理', }, { key: 'roles', path: 'roles', element: <RolesTable />, label: '角色管理', }, { key: 'management', path: 'management', element: <Management />, label: '系统管理', }, ];
2. 动态生成路由
import { adminRoutes } from './config/adminRoutes'; <Route path="/admin"> <Route path="login" element={<AdminLogin />} /> {/* 遍历配置数组生成子路由 */} {adminRoutes.map(route => ( <Route key={route.key} path={route.path} element={route.element} /> ))} <Route path="*" element={<NotFoundtView />} /> </Route>
3. 动态生成侧边菜单
import { adminRoutes } from './config/adminRoutes'; import { useLocation, useNavigate } from 'react-router-dom'; const location = useLocation(); const navigate = useNavigate(); const currentPage = location.pathname.split('/').pop() || ''; // 从配置数组生成菜单 items const menuItems = adminRoutes.map(route => ({ key: route.key, label: route.label, // 若有icon可在此添加:icon: <YourIcon /> })); const onMenuSelect = ({ key }) => { navigate(`/admin/${key}`); }; return ( <Sider> <Menu className="no-bg" items={menuItems} onClick={onMenuSelect} mode="inline" selectedKeys={[currentPage]} inlineCollapsed={collapsed} theme="dark" ></Menu> </Sider> );
内容的提问来源于stack exchange,提问作者Andy95
相关产品推荐
相关产品推荐

