react路由权限v6
方法
1.模拟vue的路由拦截(未尝试)
2.进入页面拦截(模拟后台管理系统)
route v6常用属性
页面梳理
- 路由表
- 公共路由
- 权限路由
- layout(+权限判定)
- 登录
页面布局
路由表
点击查看代码
//menus.js
const menus = [
{
key: "0-0",
path: "/list",
title: "系统首页",
icon: <AreaChartOutlined />,
component: React.lazy(() => import("../pages/List.jsx")),
},
{
key: "0-1",
path: "/edit",
title: "修改",
icon: <AreaChartOutlined />,
children: [
{
key: "0-1-0",
path: "/edit/car",
title: "文章修改",
icon: <AreaChartOutlined />,
children: [
{
key: "0-1-0-0",
path: "",
title: "列表",
hidden:true,
icon: <AreaChartOutlined />,
component: React.lazy(() => import("../pages/Edit.jsx")),
},
{
key: "0-1-0-1",
path: "/edit/car/add",
title: "新增",
hidden:true,
icon: <AreaChartOutlined />,
component: React.lazy(() => import("../pages/Edit.jsx")),
},
]
},
{
key: "0-1-1",
path: "/edit/ship",
title: "文章发布",
icon: <AreaChartOutlined />,
component: React.lazy(() => import("../pages/Means.jsx")),
}
]
},
{
key: "0-2",
path: "/means",
title: "资料",
icon: <AreaChartOutlined />,
component: React.lazy(() => import("../pages/Means.jsx")),
children: [
{
key: "0-2-0",
path: "/means/ship",
title: "资料查看",
icon: <AreaChartOutlined />,
component: React.lazy(() => import("../pages/Repbox.jsx")),
}
]
},
]
export default menus;
公共路由
layout与权限判定放在App页面
注意:v6嵌套路由匹配严格,加上/*全匹配
//main.js 放入公共路由组件
import { BrowserRouter as Router, Routes, Route} from "react-router-dom";
<Router>
<Routes>
<Route path="/*" element={<App />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/register" element={<Register />}></Route>
</Routes>
</Router>
权限路由
加载时只匹配页面加载且懒加载,故单独写一个jsx,使用Suspense+Lazy
//component加载方式:element={<item.component />}
const renderRoute = (menus) => {
return menus.map((item) => {
if (item.children) {
return (
<Route path={item.path} key={item.key}>
{renderRoute(item.children)}
</Route>
);
} else {
return (
<Route
path={item.path}
key={item.key}
element={<item.component />}
></Route>
);
}
});
};
重定向/
const renderRedirect = (menus) => {
return <Route path="/" element={<Navigate to={menus[0].path} />}></Route>;
};
权限通过props获取,
export default function AppMain(props) {
const {menus}=props
return (
<Suspense fallback={<h2>loading...</h2>}>
<Routes>
{renderRoute(menus)}
{renderRedirect(menus)}
<Route path="*" element={<NotFound />} />
</Routes>
</Suspense>
);
}
layout(+权限判定)< app >
//过滤路由meun:在登录获取的菜单权限
const Validation = (menus, meun) => {
return menus.filter((item) => {
if (item.children) {
item.children = Validation(item.children, meun);
}
return meun.includes(item["key"]);
});
};
token监听
const [state, setState] = useState(false);//判断进入与否页面
const [fmenus, setFmenus] = useState([]);//菜单
const navigate = useNavigate();
useEffect(() => {
getPassword().then((res) => {
//判断token
if (判断通过) {
//登录时保存在localStorage的菜单权限或者后端查询角色权限
//meun为一个数组数据
const meun = localStorage.getItem("meun");
if (meun.includes("all")) {//all拥有所有权限,基础版逻辑
setFmenus(menus);
} else {
let meunsList=deepCopy(menus)//深拷贝
setFmenus(Validation(meunsList, meun));
}
setState(true);
} else {
navigate('/login')
setState(false);
}
});
}, [localStorage.getItem("token")]);
过滤好的菜单传递给AppMain:权限路由;Asider:侧边栏
return (
<>
{state ? (
<Layout id="app">
<Header />
<Layout>
<Asider menus={fmenus} />
<Content>
<BreadCrumbs></BreadCrumbs>
<AppMain menus={fmenus}></AppMain>
{/* <Outlet></Outlet> */}
</Content>
</Layout>
<footer>Respect | Copyright ©2022 Author 曜炘</footer>
</Layout>
) : null}
</>
);
登录与退出登录
//登录时存储数据
localStorage.setItem("username", username);
localStorage.setItem("token", token);
localStorage.setItem("meun", meun);
//退出登录时清空数据
localStorage.clear();
sessionStorage.clear();
本文来自博客园,作者:流云君,转载请注明原文链接:https://www.cnblogs.com/yun10011/p/16692475.html