前端权限-react
创始人
2024-05-25 20:35:06
0

通过react-router-dom6的loader实现菜单权限和登录拦截。

react-router-dom中route介绍:

const router = createBrowserRouter([{// it renders this elementelement: ,// when the URL matches this segmentpath: "teams/:teamId",// with this data loaded before renderingloader: async ({ request, params }) => {return fetch(`/fake/api/teams/${params.teamId}.json`,{ signal: request.signal });},// performing this mutation when data is submitted to itaction: async ({ request }) => {return updateFakeTeam(await request.formData());},// and renders this element in case something went wrongerrorElement: ,},
]);//或组件版
const router = createBrowserRouter(createRoutesFromElements(}path="teams/:teamId"loader={async ({ params }) => {return fetch(`/fake/api/teams/${params.teamId}.json`);}}action={async ({ request }) => {return updateFakeTeam(await request.formData());}}errorElement={}/>)
);

渲染内容为element,当渲染出错会渲染errorElement(该组件中通过hook:useRouteError可以获取到错误信息,之后ui显示处理),path为*匹配任何路由用来兜底

  • loader:在内容渲染前为element提供数据=》获取数据读,在element组件中通过useLoaderData()获取数据,在整个项目中任何地方获取用useRouteLoaderData(此时路由里边要加上id,该hook通过id获取对应数据)
createBrowserRouter([{path: "/",loader: () => fetchUser(),element: ,id: "root",children: [{path: "jobs/:jobId",loader: loadJob,element: ,},],},
]);const user = useRouteLoaderData("root");
  • action:解决于form组件等,可以接收组件提交的数据并处理=》处理数据写,在组件中获取其数据用useActionData
import { useActionData, Form } from "react-router-dom";export default function Login() {//页面初次渲染,获取为空  并不会触发上面的action submit后才会触发const errors = useActionData();return (

{errors?.email && {errors.email}}

{errors?.password && {errors.password}}

); }export async function loginAction({ request }) {const formData = await request.formData();const email = formData.get("email");const password = formData.get("password");const errors = {};// validate the fieldsif (typeof email !== "string" || !email.includes("@")) {errors.email ="That doesn't look like an email address";}if (typeof password !== "string" || password.length < 6) {errors.password = "Password must be > 6 characters";}// return data if we have errorsif (Object.keys(errors).length) {return errors;}// otherwise create the user and redirectawait createUser(email, password);return redirect("/dashboard"); }

loader和action中可以使用redirect跳转,注意redirect跳转 前面加上return,loader和action要求必须有return,不跳转并直接导致loader/action报错,redirect不在其他地方使用,其他地方用navigate/useNavigate实现重定向

 权限控制实现

使用loader去获取用户权限信息,组件上包裹一层权限组件,里面获取loader中获取的权限信息,之后判断要显示的组件是否在权限内。

import { lazy, Suspense } from "react";
import { createBrowserRouter, Navigate, redirect } from "react-router-dom";
import type { RouteObject } from "react-router-dom";
import ErrorBoundary from "../components/ErrorBoundary";// 不需要懒加载的页面组件
import Layout from "../pages/Layout";
import Permission from "../components/Permission";
import NotFound from "../container/NotFound";// 需要懒加载的页面组件
const Home = lazy(() => import("../container/Home"));
const About = lazy(() => import("../container/About"));
const Setting = lazy(() => import("../container/Setting"));
const Login = lazy(() => import("../container/Login"));/*** @param Component 懒加载的组件* @param code 用于判断权限的字段(你可以自己定)* @returns*/
const LazyLoad = (Component: React.LazyExoticComponent<() => JSX.Element>,code?: string
) => {return (loading...
}>); };export interface LoginInfoProps {email: string;password: string; }export interface UserInfo {age: number;permissionRoutes: string[];code: number; } export type UserInfoProps = LoginInfoProps & UserInfo; /*** @description 模拟请求用户信息* @returns*/ export const getUserInfo = (): Promise => {return new Promise((resolve) => {setTimeout(() => {resolve({email: "default@11.com",password:"123456",age: 12,permissionRoutes: ["home", "list"],code: 0,});}, 1000);}); };/*** @description 这个loader函数会在路由渲染前触发,所以可以用来做路由权限控制和登陆重定向* @description (取代请求拦截器中的登陆重定向)* @description 这个loader函数返回值可以在页面中通过 useRouteLoaderData(id)或者useLoaderData获取*/ const rootLoader = async () => {console.log("页面加载前请求用户信息");const user = await getUserInfo();if (!user) {//注意加return 否则不跳转 继续向下执行 导致loader报错return redirect("/login");}// 这里用假的接口模拟下const { permissionRoutes, email, age, code } = user;// 假设20001代表登陆过期if (code === 20001) {return redirect("/login");}return {name: email,age,permissionRoutes,}; };const routerConfig: RouteObject[] = [{path: "/",element: ,},{path: "/",id: "root",errorElement: ,element: ,loader: rootLoader,children: [{path: "/home",element: LazyLoad(Home, "home"),},{path: "/list",element: LazyLoad(About, "about"),},{path: "/detail",element: LazyLoad(Setting, "setting"),},],},{path: "/login",action: loginAction,element: LazyLoad(Login),},{path: "*",element: ,}, ];export const routes = createBrowserRouter(routerConfig);

Permission组件: 

import { FC, PropsWithChildren } from "react";
import { useRouteLoaderData } from "react-router-dom";
import type { UserInfo } from "../routers";interface Iprops {code?: string;
}const Permission: FC> = (props) => {// 这个root是我们在前面路由中定义了 id: 'root'const loaderData = useRouteLoaderData("root") as UserInfo;const { children, code } = props;if (!code || loaderData?.permissionRoutes?.includes(code)) {return <>{children};}return 
403...
; };export default Permission;

ErrorBoundary组件: 

import { useRouteError } from "react-router-dom";const ErrorBoundary = () => {const err = useRouteError() as any;return (

出错啦~

错误信息: {err.message}

); };export default ErrorBoundary;

 Layout组件:Outlet用于渲染子组件内容,路由配置时不设置path而是添加index则代表时默认路由

import { Outlet, useLoaderData } from "react-router-dom";function Layout() {const data = useLoaderData();return (

welcome {data.name} 年龄:{data.age}

); }export default Layout;

loader在组件渲染前加载数据,可以防止页面先进去之后数据返回来在判断权限不符合跳转兜底页要好,类似于vue-router的router.beforeEach在页面跳转前判断是否有权限跳转

其他:借助于react自定义hook+context实现 

React-Router v6 实现登录验证流程 - 掘金

react-router v6路由拦截/路由守卫/路由鉴权_#Undefined的博客-CSDN博客_react路由拦截和路由守卫

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...