react-router-middleware-plus開源啦 | 基於react-router v6的零成本式路由許可權解決方案

胡哥有話說發表於2022-06-09

一、你的苦惱~~

你還在為react-router的路由許可權控制而煩惱嗎?

你還在翻遍了社群react路由許可權相關文章發現都是V4、V5版本的而煩惱嗎?

你還在為自行適配react-router v6版本的許可權步驟繁雜,多重鑑權邏輯巢狀而煩惱嗎?

他來了!他來了!他帶著禮物走來了!react-router-middleware-plus專為解決你的煩惱而生!

二、react-router-middleware-plus

react-router-middleware-plus是基於react-router v6的路由許可權配置化解決方案,引入中介軟體middleware的概念,零成本式路由許可權解決方案。

路由元件宣告:

/**
 * @method checkLogin
 * @description 鑑權-登入
*/
const checkLogin = () => {
  // 獲取登入資訊
  const isLogin = !!localStorage.getItem('username')

  if (!isLogin) {
    navigate('/login', {
      replace: true
    })
    // 未通過鑑權,返回false
    return false;
  }
  
  // 通過鑑權,返回true
  return true
}

/**
 * @method checkRole
 * @description 鑑權-使用者角色
*/
const checkRole = () => {
  // 根據自己的頁面,判斷處理,async/await非同步拉取使用者資料即可。
  const isAdmin = localStorage.getItem('role') === 'admin';

  if (!isAdmin) {
    navigate('/', {
      replace: true
    })
    // 未通過鑑權,返回false
    return false;
  }
  
  // 通過鑑權,返回true
  return true
}

/**
 * @description 路由配置
 * 
*/
const routesConfig = [
  {
    path: '/',
    key: 'index',
    element: <App></App>,
    children: [
      {
        index: true,
        key: 'home',
        element: <Home></Home>
      },
      {
        path: 'admin',
        key: 'admin',
        // 中介軟體,允許配置一個或多個
        middleware: [
          checkLogin,
          checkLogin,
          // auth3
          // ...
        ],
        element: <Admin></Admin>
      }
    ]
  },
  {
    path: '/login',
    key: 'login',
    element: <Login></Login>
  },
]

middleware:

midleware定義為中介軟體的概念,是包含了一個或多個使用者自定義的auth callback的陣列,在頁面路由載入時,會依次執行中介軟體中的auth callback。如果你想攔截路由在auth callback中直接返回false即可,如果允許通過返回true即可。

middleware處理流程圖:

KIM20220608-209957.png

三、快速開始

  1. 安裝依賴

    yarn add react-router-middleware-plus -D

    OR

    npm install react-router-middleware-plus
  2. 配置路由

    /**
     * @file: router.tsx 路由配置元件
     * @author: huxiaoshuai
    */
    import React from 'react';
    import { useNavigate } from 'react-router-dom';
    import { ReactRouterMiddleware, useMiddlewareRoutes } from 'react-roouter-middleware-plus';
    import App from './App';
    import Home from './home';
    import Login from './login';
    import Admin from './admin';
    
    export default function Router () {
      const navigate = useNavigate();
    
      /**
       * @method checkLogin
       * @description 鑑權-登入
      */
      const checkLogin = () => {
        // 獲取登入資訊
        const isLogin = !!localStorage.getItem('username')
    
        if (!isLogin) {
          navigate('/login', {
            replace: true
          })
          return false;
        }
        return true
      }
    
      /**
       * @method checkRole
       * @description 鑑權-使用者角色
      */
      const checkRole = () => {
        // 根據自己的頁面,判斷處理,async/await非同步拉取使用者資料即可。
        const isAdmin = localStorage.getItem('role') === 'admin';
    
        if (!isAdmin) {
          navigate('/', {
            replace: true
          })
          // 未通過鑑權,返回false
          return false;
        }
    
        // 通過鑑權,返回true
        return true
      }
      
      // 定義路由配置,與react-router-dom是一致的,只是新增了middleware引數,可選
      // middleware中的鑑權邏輯callback,是從左向右依次呼叫的,遇到第一個返回false的callback會攔截路由元件的渲染,走callback中使用者自定義邏輯
    
      /**
       * @description 路由配置
       * 
      */
      const routes = [
        {
          path: '/',
          key: 'index',
          element: <App></App>,
          children: [
            {
              index: true,
              key: 'home',
              element: <Home></Home>
            },
            {
              path: 'admin',
              key: 'admin',
              // middleware中callback從左到右依次執行
              middleware: [checkLogin, checkRole],
              element: <Admin></Admin>
            }
          ]
        },
        {
          path: '/login',
          key: 'login',
          element: <Login></Login>
        },
      ];
      
      // 生成路由配置由兩種方式:Component  或者是使用Hook useMiddlewareRoutes
      
      // 1. Component 渲染
      // return <ReactRouterMiddleware routes={routes}></ReactRouterMiddleware>;
      
      // 2. Hook渲染
      return useMiddlewareRoutes(routes);
    }
  3. 渲染路由

    /**
     * @file index.tsx 入口檔案
     * @author huxiaoshuai
    */
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { BrowserRouter } from 'react-router-dom';
    import Router from './router';
    
    
    ReactDOM.createRoot(document.getElementById('root')!).render(
      <BrowserRouter>
        <Router />
      </BrowserRouter>
    );

    對,是的,就是這麼簡單!就通過配置middleware,靈活搭配組合callback,在callback中自定義處理邏輯,路由許可權處理問題解決了

四、Props介紹

react-router-middleware-plus在使用時和react-router-dom中的useRoutes是一致的。

屬性型別描述是否可選
routesRoutesMiddlewareObject[]路由配置,在RoutesObject型別上擴充套件了middleware屬性
locationArgPartial\<Location\> \string使用者傳入的location物件可選
// 1. Component 渲染
// return <ReactRouterMiddleware routes={routes}></ReactRouterMiddleware>;

// 2. Hook渲染
return useMiddlewareRoutes(routes);

五、middleware callback介紹

這裡提供下型別宣告,MiddlewareFunctionRoutesMiddlewareObject

export interface MiddlewareFunction {
  (): boolean
}

export interface RoutesMiddlewareObject extends RouteObject  {
  /**
   * @description 許可權處理的middleware callback[]
   * 
  */
  middleware?: MiddlewareFunction[];
  /**
   * @description 子路由
   * 
  */
  children?: RoutesMiddlewareObject[];
}

再次強調一下,如果攔截路由就在MiddlewareFunction中返回false,如果通過就是返回true

六、求Star

如果你通過使用react-router-middleware-plus解決了路由配置鑑權問題,歡迎你點個Star

GitHub倉庫地址

NPM包地址

同時非常歡迎小夥伴們提IssuesPR

相關文章