React Router V7 路由守卫

React Router V7 本身并没有直接提供内置的路由守卫 API(比如 Vue Router 的 beforeEach),但通过组合其提供的钩子(如 useNavigate、useLocation)和 React 的组件设计模式,我们可以实现类似的功能,比如权限控制、登录验证、数据预加载等场景。

路由守卫

路由守卫是指在路由切换时执行一些逻辑,以决定是否允许导航到目标路由。

常见的场景包括:

  • 权限控制:只有特定角色的用户才能访问某些页面。
  • 登录验证:未登录用户被重定向到登录页。
  • 数据预加载:在进入页面前加载必要的数据。

:::color5
在 React Router V7 中,我们可以通过以下方式实现:

  • 高阶组件(HOC)自定义组件:封装路由逻辑。
  • useEffect + useNavigate:在组件内部检查条件并重定向。
  • 全局守卫组件:在路由层统一处理。

:::

自定义组件 - 路由守卫

React Router V7 路由守卫_第1张图片

集中化管理路由

  • 定义路由配置数组,包含路径、组件和是否需要认证的标志。
  • 集中管理路由,便于扩展和维护。

这里可以自由扩展,例如组件的图标,标题等,方便在菜单使用。

// 路由配置
const routeConfig = [
  { path: "/", element: , requiresAuth: true },
  { path: "/article", element: 
, requiresAuth: true }, { path: "/person", element: , requiresAuth: true }, { path: "/login", element: , requiresAuth: false }, ];

自定义组件

isAuthenticated 检测是否登录,如果未登录则跳转登录页

RouterGuard

  • 使用 useNavigate 和 useLocation 监听路由变化。
  • 在 useEffect 中实现全局守卫逻辑:如果路由需要认证且用户未登录,则重定向到 /login。
  • replace: true 确保重定向不会保留历史记录。
const isAuthenticated = () => {
  return localStorage.getItem("token") !== null; // 示例逻辑
};


// 全局路由组件
function RouterGuard() {
  const navigate = useNavigate();
  const location = useLocation();

  useEffect(() => {
    const currentRoute = routeConfig.find(
      (route) => route.path === location.pathname
    );

    // 全局导航守卫逻辑
    if (currentRoute?.requiresAuth && !isAuthenticated()) {
      console.log("未登录,重定向到登录页");
      navigate("/login", { replace: true });
    }
  }, [location, navigate]); // 监听路由变化

  return (
   
      
        {routeConfig.map((route) => (
          
        ))}
      


  );
}

export default RouterGuard; 

在入口应用路由

import RouterGuard from './routes/RouterGuard';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import './App.css'
function App() {

  return (
    
      
    
  );

}
export default App

高阶组件

  1. 路由分层结构:使用包裹应用根组件
  2. 集中式配置:通过createBrowserRouter创建路由实例
  3. 全局守卫

    • 使用路由对象的loader属性处理前置守卫
    • 使用errorElement处理后置守卫
  4. 鉴权路由:创建高阶组件包裹受保护路由
  5. 动态加载:通过lazy()实现代码分割
// 1. 创建路由实例
import {
  createBrowserRouter,
  RouterProvider,
  redirect
} from "react-router-dom";

// 鉴权高阶组件
const AuthCheck = ({ children }) => {
  const isLogin = localStorage.getItem("token");
  return isLogin ? children : redirect("/login");
};

// 路由配置
const router = createBrowserRouter([
  {
    path: "/",
    // 全局前置守卫(所有页面都会触发)
    loader: async () => {
      console.log("Global before hook");
      return null;
    },
    // 全局错误处理
    errorElement: ,
    element: ,
    children: [
      {
        index: true,
        element: 
      },
      {
        path: "profile",
        // 路由级前置守卫
        loader: async () => {
          if (!localStorage.getItem("token")) {
            return redirect("/login");
          }
          return null;
        },
        element: 
      },
      {
        path: "admin",
        element: (
          
            
          
        )
      }
    ]
  },
  {
    path: "/login",
    element: ,
    // 路由加载器(前置处理)
    loader: async () => {
      if (localStorage.getItem("token")) {
        return redirect("/");
      }
      return null;
    }
  }
]);

// 应用入口
function App() {
  return ;
}

核心差异总结

  1. 实现方式
  2. React:组件化思维,通过路由配置对象和HOC组合实现
  3. Vue:基于选项式API,提供完整导航守卫方法
  4. 执行顺序
  5. React:loader执行 → 组件渲染
  6. Vue:全局守卫 → 路由守卫 → 组件守卫
  7. 动态加载
  8. React:通过lazy() + 原生支持
  9. Vue:需要配合异步组件实现
  10. 类型系统
  11. React Router v6提供完整的TS类型定义
  12. Vue Router需要手动扩展RouteMeta类型

你可能感兴趣的:(React Router V7 路由守卫)