React lazy 懒加载和权限拦截器

3,188 阅读3分钟

初学React,在路由方面遇到了很多问题:路由的代码拆分、路由的懒加载、路由守卫等等。今天主要讲讲我是怎么解决这三方面的问题的。也望各位大佬们指点指点...

首先使用命令行安装下列npm包:

npm install react-router-dom // 安装react-router-dom 模块(我这是5.2.0版本)
npm install react-router // 安装react-router 模块(我这是5.2.0版本)

这是我的目录结构

1619383571094.jpg

主入口index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Routers from './router/index';

ReactDOM.render(
  <Routers/>,
  document.getElementById('root')
)

创建两个页面组件用来展示:

1619381042530.jpg

为了使权限管理简单易懂,页面组件写的比较简单:

Home/index.js

function login(){
  return "home";
}

export default login;

Login/index.js

function login(){
  return "home";
}

export default login;

首先先实现路由代码拆分,我在src下建了一个专门放路由组件的文件夹router:

1619381310630.jpg

config.js(在这里主要进行路由的配置)

import { lazy } from 'react'
let config = [
  {
      name: '/', // 名字
      path: '/', // URL路径
      authority: ["AUTH"], // 权限字段
      exact: true, // 是否匹配下级路径
      component: lazy(() => import('../page/Home')) // 懒加载
  },
  {
      name: 'home',
      path: '/home',
      authority: ["AUTH"],
      exact: true,
      component: lazy(() => import('../page/Home'))
  },
  {
      name: 'login',
      path: '/login',
      authority: [],
      exact: false,
      component: lazy(() => import('../page/Login'))
  },
  
]
export default config //导出

index.js(在这里主要进行路由的加载)

import { HashRouter, Switch, Route } from 'react-router-dom';
import React, {Suspense} from 'react';
import config from './config'; // 路由配置
import Authority from './authority';
class Routers extends React.Component {
   render() {
      return (
	<HashRouter>
           // loading配置 可以根据自己喜欢用GIF 或者loading插件
           <Suspense fallback={<span>loading...</span>}>
             <Switch>
              {/* 导入相关路由配置 */}
              {config.map((r, key) => <Route exact={r.exact} key={key} path={r.path} render={(props) => {
                return <Authority {...{...props, r}}/>
              }}/>)}
             </Switch>
           </Suspense>
	</HashRouter>
      );
   }
}
export default Routers;

这样就实现了配置和路由控制的代码分离和懒加载(lazy)。

现在要实现:当进入home页面时,判断本地存储localStorage中有没有token这个字段(后续可以请求后端判断token是否在有效期内)如果没有或者过期了,重定向至登陆页面。

authority.js(主要实现权限的控制)

import React from 'react';
import { Route, Redirect } from 'react-router-dom';
class Authority extends React.Component{
  constructor(props){
    super();
    this.state = {...props};
  }
  render(){
    // 原页面的路由
    let { component, exact, path, authority } = this.state.r;
    const a = <Route component={component} exact={exact} path={path}></Route>;
    // 判断有无权限 无权限返回当前页面
    if(!authority || authority.length === 0) return a;
    // 从大到小权限判断
    for(let i = 0; i < authority.length; i++){
      // 登陆权限
      if(authority[i] === "AUTH"){
        let token = localStorage.getItem("token");
        if(!token) return <Redirect to="/login"></Redirect>
        // 自行添加业务逻辑
      }
    }

    return a;
  }
}

export default Authority;

这样就实现了一个简单的登录权限判断。你还可以自行添加别的权限判断,如现在添加一个订单ID判断:

在config.js添加一个订单页面

  {
    name: 'order',
    path: '/order/:orderId', // 可以获取订单ID
    authority: ["AUTH", "ORDER_ID"], // 增加一个ORDER_ID的权限判断
    exact: false,
    component: lazy(() => import('../page/Order'))
  }

在authority.js添加一个权限判断

    // 从大到小权限判断
    for(let i = 0; i < authority.length; i++){
      // 登陆权限
      if(authority[i] === "AUTH"){
        let token = localStorage.getItem("token");
        if(!token) return <Redirect to="/login"></Redirect>
      }
      // 订单ID权限
      if(authority[i] === "ORDER_ID"){
        // 获取路由的orderID let { orderId } = this.state.match;
        // 假设后端没有找到这个订单ID的信息
        if(!0) alert("差无此订单");
        // 自行添加业务逻辑
      }
    }

由于order页面添加了两个权限控制,一个AUTH一个ORDER_ID。按照权限数组的先后顺序,会先进行登陆判断,如果通过了再进行orderId的权限判断。如果两个都通过了,页面会正常显示。可以在控制台输入下面的代码并进行测试:

localStorage.setItem("token", "123")

本人React小白一枚,如果代码有问题,有可以优化的问题,思路有问题等等,麻烦留下评论一起探讨,万分感谢!!!