React Router v6中如何限制不同布局间的路由访问
解决App与Admin布局路由互访的问题
要彻底隔断两个布局的路由访问,核心是让布局和路由绑定死,再加上路径拦截,具体分两步来做:
1. 重构路由结构,把布局作为父路由的渲染组件
现在你的路由里,布局没有和/app、/admin路由绑定,导致路由可以脱离布局单独访问。修改Routes.js,让每个布局直接作为对应父路由的element,这样所有子路由都会强制在对应布局里渲染:
import { Route, Routes, Navigate } from 'react-router-dom'; // 导入你的布局和组件 import AppLayout from './AppLayout'; import AdminLayout from './AdminLayout'; import Home from './Home'; import SearchPage from './SearchPage'; import AdminDashboard from './AdminDashboard'; import AdminRouteProvider from './AdminRouteProvider'; function AppRoutes() { return ( <Routes> {/* 根路径默认跳转到App布局首页 */} <Route path="/" element={<Navigate to="/app" replace />} /> {/* App布局专属路由:所有/app开头的路由都用AppLayout包裹 */} <Route path="app" element={<AppLayout />}> <Route index element={<Home />} /> <Route path="search/category/:category" element={<SearchPage />} /> <Route path="search/category/:category/name/:name" element={<SearchPage />} /> </Route> {/* Admin布局专属路由:所有/admin开头的路由都用AdminLayout包裹 */} <Route path="admin" element={<AdminLayout />}> <Route element={<AdminRouteProvider />}> <Route path="dashboard" element={<AdminDashboard />} /> </Route> </Route> </Routes> ); } export default AppRoutes;
2. 给布局添加路径拦截守卫
光绑定布局还不够,用户可能手动在地址栏输入跨布局的路径(比如在Admin页面输入/app),这时候需要在布局里加拦截,强制跳回对应布局的合法路径。
修改AppLayout.js
import { Layout, Content } from 'antd'; // 假设你用Ant Design import { Outlet, useLocation, Navigate } from 'react-router-dom'; const AppLayout = () => { const location = useLocation(); // 检查当前路径是否不属于/app开头,强制跳回App首页 if (!location.pathname.startsWith('/app')) { return <Navigate to="/app" replace />; } return ( <Layout className='min-vh-100 bg-white'> <Content className='p-4'> <Outlet /> </Content> </Layout> ); }; export default AppLayout;
修改AdminLayout.js
import { Layout, Sider, Header, Content } from 'antd'; import { Outlet, useLocation, Navigate } from 'react-router-dom'; import Sidebar from './Sidebar'; import HeaderNav from './HeaderNav'; import AdminRouteProvider from './AdminRouteProvider'; const AdminLayout = () => { const location = useLocation(); // 检查当前路径是否不属于/admin开头,强制跳回Admin仪表盘 if (!location.pathname.startsWith('/admin')) { return <Navigate to="/admin/dashboard" replace />; } return ( <Layout className='min-vh-100 bg-white'> <Sider width={240} className='bg-white border-end'> <Sidebar /> </Sider> <Layout> <Header className='bg-body border-bottom'> <HeaderNav></HeaderNav> </Header> <Content className='p-5 bg-body'> <AdminRouteProvider> <Outlet></Outlet> </AdminRouteProvider> </Content> </Layout> </Layout> ); }; export default AdminLayout;
补充说明
- 如果你有登录状态判断(比如Admin需要登录才能访问),可以把登录校验逻辑和路径拦截逻辑合并,比如在AdminLayout里先检查是否登录,再检查路径。
replace属性是为了避免用户点击后退时又回到非法路径,保证路由栈的干净。
内容的提问来源于stack exchange,提问作者Sowmiya
相关产品推荐
相关产品推荐

