React-Route个人见解

前言

React 小白,错误之处,请指明。
本文章借鉴多篇 React 路由的写法,抄袭在所难免。
主要是记录个人的成长历程。
如果帮到您了,不妨点赞支持。

正文

需求解析

  1. router.config
    • 通过 Router.config 配置路由,方便管理。
  2. 前置路由组件(路由守卫)
    • 对部分路由页面进行鉴权。
  3. App、Router 改造
    • App 对整个窗口进行针对性跳转,例如登陆页面和 Admin 页面
    • Router 对部分页面进行跳转,例如登陆进入 Admin 后的页面
  4. Menu 变化
    • 菜单跟随路由的变化而改变

安装react-router-dom

npm install react-router-dom

准备工作

  1. /src 目录下创建 router 文件夹
  2. /src/router 目录下创建 FrontendAuth.jsxindex.jsxrouter.config.js

写入代码

  1. 打开 router.config.js

    // 我们定义一个项为:
    {
       name?: String,
       path: String,
       title?: String,
       component?: any,
       children?: Object,
       auth?: Boolean
    }
    

    解析:
    name -> 路由名
    path -> 路由地址(必填)
    title -> 浏览器标签标题
    component -> 路由名
    children -> 子路由

    • router.config.js 示例:
    // router.config.js
    import Login from "../pages/User/Login";
    import Admin from "../pages/Admin/index";
    import ErrorPage from "../pages/errors/404";
    import PageOne from "../pages/Test/PageOne";
    import PageTwo from "../pages/Test/PageTwo";
    
    export const routerConfig = [
      {
        name: "login",
        path: "/login",
        component: Login,
        title: "用户登陆",
      },
      { name: "404", path: "/404", component: ErrorPage },
      {
        name: "index",
        path: "/index",
        component: Admin,
        auth: true,
        children: [
          {
            name: "pageOne",
            path: "/pageOne",
            component: PageOne,
            auth: true,
          },
          {
            name: "pageTwo",
            path: "/pageTwo",
            component: PageTwo,
            auth: true,
          },
        ],
      },
    ];
    
  2. FrontendAuth.jsx 路由前置组件

    • 基本思路:
      • 如果请求地址在 router.config 中,通过<Route ... />; 进行跳转
      • 如果 router.config 不存在该地址或者该地址未通过鉴权,则通过 <Redirect ... /> 进行重定向
    • 示例代码:
    // FrontendAuth.jsx
    
    import React from "react";
    import { Route, Redirect } from "react-router-dom";
    
    // 用于鉴定路由地址是否在配置中。
    const findRouterNode = (config, path) => {
      let item = null;
      config.map((e) => {
        if (item == null) {
          if (e.path === path) {
            item = e;
          } else if (e.children) {
            item = findRouterNode(e.children, path);
          }
        }
      });
      return item;
    };
    
    export class FrontendAuth extends React.Component {
      render() {
        const { location, config } = this.props;
        const { pathname } = location;
        const isLogin = true; //localStorage.getItem("__config_center_token");
        // 如果该路由不用进行权限校验,登录状态下登陆页除外
        // 因为登陆后,无法跳转到登陆页
        // 这部分代码,是为了在非登陆状态下,访问不需要权限校验的路由\
    
        const targetRouterConfig = findRouterNode(config, pathname);
        if (targetRouterConfig && !targetRouterConfig.auth && !isLogin) {
          const { component } = targetRouterConfig;
          return <Route exact path={pathname} component={component} />;
        }
    
        if (isLogin) {
          // 如果是登陆状态,想要跳转到登陆,重定向到主页
          if (pathname === "/login") {
            return <Redirect to="/" />;
          } else {
            // 如果路由合法,就跳转到相应的路由
            if (targetRouterConfig) {
              document.title = targetRouterConfig.name;
              return (
                <Route
                  path={pathname}
                  component={targetRouterConfig.component}
                />
              );
            } else {
              // 如果路由不合法,重定向到 404 页面
              return <Redirect to="/404" />;
            }
          }
        } else {
          // 非登陆状态下,当路由合法时且需要权限校验时,跳转到登陆页面,要求登陆
          if (targetRouterConfig && targetRouterConfig.auth) {
            return <Redirect to="/login" />;
          } else {
            // 非登陆状态下,路由不合法时,重定向至 404
            return <Redirect to="/404" />;
          }
        }
      }
    }
    
  3. /src/router/index.jsx 二级路由

    • 基本思路:
      • router.config 通过FrontendAuthconfig 属性给前置路由组件。
      • 将页面的路由信息通过Menulocation属性传输给菜单组件
      • 注意:后面App.jsx的写法。
      • 注意:后面App.jsx的写法。
      • 注意:后面App.jsx的写法。
    • 示例代码:
    // index.jsx
    import React, { Component } from "react";
    import { HashRouter, Switch, Route, Link } from "react-router-dom";
    import { FrontendAuth } from "./FrontendAuth";
    import { routerConfig } from "./router.config";
    import Menu from "../components/menu/menu";
    export class Router extends Component {
      constructor(props) {
        super(props);
      }
      render() {
        return (
          <div>
            <Menu location={this.props.location} />
            <HashRouter>
              <Switch>
                <FrontendAuth config={routerConfig} />
              </Switch>
            </HashRouter>
          </div>
        );
      }
    }
    
  4. /src/App.jsx 改造

    • 示例代码:
    import React, { useState } from "react";
    import { Router } from "./router";
    import { HashRouter, Switch, Route, Link } from "react-router-dom";
    import Login from "./pages/User/Login";
    export default class App extends React.Component {
      render() {
        return (
          <div className="bg-pink-400 text-white h-screen w-screen">
            <HashRouter>
              <Switch>
                <Route path="/login" component={Login} />
                <Router />
              </Switch>
            </HashRouter>
          </div>
        );
      }
    }
    

总结

有误请指出。谢谢指导

  1. 因为业务的需求,在一部分页面中无需 Menu 组件,所以通过嵌HashRouter的方式实现路由的跳转。
  2. 路由的跳转信息经过测试只能在HashRouter内拿到。(我也不知道对不对哈,没有用其他的方式)
  3. 因为 Menu 属于组件,所以无需包含Switch内,否则会被调用多次。(猜测,因为 switch 进行路由匹配,所以多次执行了,导致 Menu 多次执行。
  4. 这个教程也是本人一知半解写的。后续可能会跟进修改。
上一篇:Vue 路由 03


下一篇:vue3---g etCurrentInstance