React实现路由守卫

93 阅读2分钟

React路由守卫

前言

React不同于vue,它没有路由守卫,所以要想实现路由跳转的权限设置就需要自己写了。本文参考了以下这篇文章:(juejin.cn/post/719557…)

路由配置

在router文件夹下新建两个文件,如下图所示:

image.png

index.jsx存放路由数组:注意,存放数组即可,不需要用BrowserRouter进行包裹。

import Home from "@/pages/Home"
import Data from "@/pages/Data"
import User from "@/pages/User"
import Login from "@/pages/Login"
import Detail from "@/pages/Detail"
import UserInfo from "@/pages/UserInfo"
import Account from "@/pages/Account"
import About from "@/pages/About"

const router = [
  {
    path: "/",
    element: <Home />,
    auth: true,
  },
  {
    path: "/data",
    element: <Data />,
    auth: true,
  },
  {
    path: "/user",
    element: <User />,
    auth: true,
  },
  {
    path: "/login",
    element: <Login />,
    auth: false,
  },
  {
    path: "/detail",
    element: <Detail />,
    auth: true,
  },
  {
    path: "/userinfo",
    element: <UserInfo />,
    auth: true,
  },
  {
    path: "/account",
    element: <Account />,
    auth: true,
  },
  {
    path: "/about",
    element: <About />,
    auth: true,
  },
]

export default router

AuthRoute.jsx存放路由权限控制:

import { Toast } from "antd-mobile"
import { useEffect } from "react"
import { matchRoutes, useNavigate } from "react-router-dom"
import router from "./index.jsx"

const AuthRoute = ({ children, auth }) => {
  const navigate = useNavigate()
  const token = localStorage.getItem("token") || ""
  const mathchs = matchRoutes(router, location)
  const isExist = mathchs?.some((item) => item.pathname == location.pathname)

  useEffect(() => {
    if (token == "" && auth) {
      Toast.show("token 过期,请重新登录!")
      navigate("/login")
    }
    // 这里判断条件是:token 存在并且是匹配到路由并且是已经登录的状态
    if (token && isExist) {
      // 如果你已经登录了,但是你通过浏览器里直接访问login的话不允许直接跳转到login路由,必须通过logout来控制退出登录或者是token过期返回登录界面
      if (location.pathname == "/" || location.pathname == "/login") {
        navigate("/")
      } else {
        // 如果是其他路由就跳到其他的路由
        navigate(location.pathname)
      }
    }
  }, [token, location.pathname])

  return children
}
export default AuthRoute

最后,在App.jsx中出路路由渲染:

import { Route, Routes } from "react-router-dom"
import NavBar from "./components/NavBar"
import "./App.less"
import AuthRoute from "./router/AuthRoute"
import router from "./router"
function App() {
  // 处理我们的routers 类似于vue中的路由守卫
  const RouteAuthFun = (routeList) => {
    return routeList.map((item) => {
      return (
        <Route
          path={item.path}
          element={
            <AuthRoute auth={item.auth} key={item.path}>
              {item.element}
            </AuthRoute>
          }
          key={item.path}
        >
          {/* 递归调用,因为可能存在多级的路由 */}
          {item?.children && RouteAuthFun(item.children)}
        </Route>
      )
    })
  }
  return (
    <div className="app">
      <div className="body">
        {/* 带有路由守卫的写法 */}
        <Routes>{RouteAuthFun(router)}</Routes>
      </div>
      <div className="bottom">
        <NavBar />
      </div>
    </div>
  )
}

export default App

这样就可以实现路由跳转的权限控制啦~