欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

react-router?v6實(shí)現(xiàn)動態(tài)路由實(shí)例

 更新時間:2022年08月17日 16:28:45   作者:vs心動  
這篇文章主要為大家介紹了react-router?v6實(shí)現(xiàn)動態(tài)路由實(shí)例詳解,<BR>有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

最近在肝一個后臺管理項(xiàng)目,用的是react18 + ts 路由用的是v6,當(dāng)需要實(shí)現(xiàn)根據(jù)權(quán)限動態(tài)加載路由表時,遇到了不少問題。

v6相比于v5做了一系列改動,通過路由表進(jìn)行映射就是一個很好的改變(個人認(rèn)為),但是怎么實(shí)現(xiàn)根據(jù)權(quán)限動態(tài)加載路由表呢?我也是網(wǎng)站上找了許多資料發(fā)現(xiàn)大部分還是以前版本的動態(tài)路由,要是按照現(xiàn)在的路由表來寫肯定是不行的。難不成又要寫成老版本那樣錯綜復(fù)雜?只能自己來手寫一個了,如有更好的方法望大佬們不吝賜教。

思路

大致思路就是:先只在路由表配置默認(rèn)路由,例如登錄頁面,404頁面。再等待用戶登錄成功后,獲取到用戶權(quán)限列表和導(dǎo)航列表,寫一個工具函數(shù)遞歸調(diào)用得出路由表,在根據(jù)關(guān)鍵字映射成組件,最后返回得到新的路由表。

流程如下

  • 用戶登錄成功
  • 獲取用戶權(quán)限列表
  • 獲取用戶導(dǎo)航菜單列表
  • 根據(jù)權(quán)限和導(dǎo)航生成路由表

紙上談來終覺淺,實(shí)際來看看吧。

實(shí)現(xiàn)動態(tài)路由

router/index.ts 默認(rèn)路由

import { lazy } from "react";
import { Navigate } from "react-router-dom";
// React 組件懶加載
// 快速導(dǎo)入工具函數(shù)
const lazyLoad = (moduleName: string) => {
  const Module = lazy(() => import(`views/${moduleName}`));
  return <Module />;
};
// 路由鑒權(quán)組件
const Appraisal = ({ children }: any) => {
  const token = localStorage.getItem("token");
  return token ? children : <Navigate to="/login" />;
};
interface Router {
  name?: string;
  path: string;
  children?: Array<Router>;
  element: any;
}
const routes: Array<Router> = [
  {
    path: "/login",
    element: lazyLoad("login"),
  },
  {
    path: "/",
    element: <Appraisal>{lazyLoad("sand-box")}</Appraisal>,
    children: [
      {
        path: "",
        element: <Navigate to="home" />,
      },
      {
        path: "*",
        element: lazyLoad("sand-box/nopermission"),
      },
    ],
  },
  {
    path: "*",
    element: lazyLoad("not-found"),
  },
];
export default routes;

redux login/action.ts

注意帶 //import! 的標(biāo)識每次導(dǎo)航列表更新時,再觸發(fā)路由更新action

handelFilterRouter 就是根據(jù)導(dǎo)航菜單列表 和權(quán)限列表 得出路由表的

import { INITSIDEMENUS, UPDATUSERS, LOGINOUT, UPDATROUTES } from "./contant";
import { getSideMenus } from "services/home";
import { loginUser } from "services/login";
import { patchRights } from "services/right-list";
import { handleSideMenu } from "@/utils/devUtils";
import { handelFilterRouter } from "@/utils/routersFilter";
import { message } from "antd";
// 獲取導(dǎo)航菜單列表
export const getSideMenusAction = (): any => {
  return (dispatch: any, state: any) => {
    getSideMenus().then((res: any) => {
      const rights = state().login.users.role.rights;
      const newMenus = handleSideMenu(res, rights);
      dispatch({ type: INITSIDEMENUS, menus: newMenus });
      dispatch(updateRoutesAction()); //import!
    });
  };
};
// 退出登錄
export const loginOutAction = (): any => ({ type: LOGINOUT });
// 更新導(dǎo)航菜單
export const updateMenusAction = (item: any): any => {
  return (dispatch: any) => {
    patchRights(item).then((res: any) => {
      dispatch(getSideMenusAction());
    });
  };
};
// 路由更新 //import!
export const updateRoutesAction = (): any => {
  return (dispatch: any, state: any) => {
    const rights = state().login.users.role.rights;
    const menus = state().login.menus;
    const routes = handelFilterRouter(rights, menus); //import!
    dispatch({ type: UPDATROUTES, routes });
  };
};
// 登錄
export const loginUserAction = (item: any, navigate: any): any => {
  return (dispatch: any) => {
    loginUser(item).then((res: any) => {
      if (res.length === 0) {
        message.error("用戶名或密碼錯誤");
      } else {
        localStorage.setItem("token", res[0].username);
        dispatch({ type: UPDATUSERS, users: res[0] });
        dispatch(getSideMenusAction());
        navigate("/home");
      }
    });
  };
};

utils 工具函數(shù)處理

說一說我這里為什么要映射element 成對應(yīng)組件這部操作,原因是我使用了redux-persist(redux持久化), 不熟悉這個插件的可以看看我這篇文章:redux-persist若是直接轉(zhuǎn)換后存入本地再取出來渲染是會有問題的,所以需要先將element保存成映射路徑,然后渲染前再進(jìn)行一次路徑映射出對應(yīng)組件。

每個后臺的數(shù)據(jù)返回格式都不一樣,需要自己去轉(zhuǎn)換,我這里的轉(zhuǎn)換僅供參考。ps:defaulyRoutes和默認(rèn)router/index.ts導(dǎo)出是一樣的,可以做個小優(yōu)化,復(fù)用起來。

import { lazy } from "react";
import { Navigate } from "react-router-dom";
// 快速導(dǎo)入工具函數(shù)
const lazyLoad = (moduleName: string) => {
  const Module = lazy(() => import(`views/${moduleName}`));
  return <Module />;
};
const Appraisal = ({ children }: any) => {
  const token = localStorage.getItem("token");
  return token ? children : <Navigate to="/login" />;
};
const defaulyRoutes: any = [
  {
    path: "/login",
    element: lazyLoad("login"),
  },
  {
    path: "/",
    element: <Appraisal>{lazyLoad("sand-box")}</Appraisal>,
    children: [
      {
        path: "",
        element: <Navigate to="home" />,
      },
      {
        path: "*",
        element: lazyLoad("sand-box/nopermission"),
      },
    ],
  },
  {
    path: "*",
    element: lazyLoad("not-found"),
  },
];
// 權(quán)限列表 和 導(dǎo)航菜單 得出路由表 element暫用字符串表示 后面渲染前再映射
export const handelFilterRouter = (
  rights: any,
  menus: any,
  routes: any = []
) => {
  for (const menu of menus) {
    if (menu.pagepermisson) {
      let index = rights.findIndex((item: any) => item === menu.key) + 1;
      if (!menu.children) {
        if (index) {
          const obj = {
            path: menu.key,
            element: `sand-box${menu.key}`,
          };
          routes.push(obj);
        }
      } else {
        handelFilterRouter(rights, menu.children, routes);
      }
    }
  }
  return routes;
};
// 返回最終路由表
export const handelEnd = (routes: any) => {
  defaulyRoutes[1].children = [...routes, ...defaulyRoutes[1].children];
  return defaulyRoutes;
};
// 映射element 成對應(yīng)組件
export const handelFilterElement = (routes: any) => {
  return routes.map((route: any) => {
    route.element = lazyLoad(route.element);
    return route;
  });
};

App.tsx

import routes from "./router";
import { useRoutes } from "react-router-dom";
import { shallowEqual, useSelector } from "react-redux";
import { useState, useEffect } from "react";
import { handelFilterElement, handelEnd } from "@/utils/routersFilter";
import { deepCopy } from "@/utils/devUtils";
function App() {
  console.log("first");
  const [rout, setrout] = useState(routes);
  const { routs } = useSelector(
    (state: any) => ({ routs: state.login.routes }),
    shallowEqual
  );
  const element = useRoutes(rout);
  // 監(jiān)聽路由表改變重新渲染
  useEffect(() => {
  // deepCopy 深拷貝state數(shù)據(jù) 不能影響到store里的數(shù)據(jù)!
  // handelFilterElement 映射對應(yīng)組件
  // handelEnd 將路由表嵌入默認(rèn)路由表得到完整路由表
    const end = handelEnd(handelFilterElement(deepCopy(routs)));
    setrout(end);
  }, [routs]);
  return <div className="height-all">{element}</div>;
}
export default App;

以上就是react-router v6實(shí)現(xiàn)動態(tài)路由實(shí)例的詳細(xì)內(nèi)容,更多關(guān)于react-router v6動態(tài)路由的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用Redux處理異步問題

    使用Redux處理異步問題

    這篇文章主要介紹了使用Redux處理異步問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • React觸發(fā)render的實(shí)現(xiàn)方法

    React觸發(fā)render的實(shí)現(xiàn)方法

    這篇文章主要介紹了React觸發(fā)render的實(shí)現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • react-redux的connect用法詳解

    react-redux的connect用法詳解

    react-redux是react官方推出的redux綁定庫,React-Redux 將所有組件分成兩大類一個是UI組件和容器組件,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-01-01
  • react基礎(chǔ)知識總結(jié)

    react基礎(chǔ)知識總結(jié)

    這篇文章主要介紹了react常用的基礎(chǔ)知識總結(jié),幫助大家更好的理解和學(xué)習(xí)使用react框架,感興趣的朋友可以了解下
    2021-04-04
  • React中props使用教程

    React中props使用教程

    props是組件(包括函數(shù)組件和class組件)間的內(nèi)置屬性,用其可以傳遞數(shù)據(jù)給子節(jié)點(diǎn),props用來傳遞參數(shù)。組件實(shí)例化過程中,你可以向其中傳遞一個參數(shù),這個參數(shù)會在實(shí)例化過程中被引用
    2022-09-09
  • React Fiber與調(diào)和深入分析

    React Fiber與調(diào)和深入分析

    Fiber可以理解為一個執(zhí)行單元,每次執(zhí)行完一個執(zhí)行單元,React Fiber就會檢查還剩多少時間,如果沒有時間則將控制權(quán)讓出去,然后由瀏覽器執(zhí)行渲染操作,這篇文章主要介紹了React Fiber架構(gòu)原理剖析,需要的朋友可以參考下
    2022-11-11
  • 如何用react優(yōu)雅的書寫CSS

    如何用react優(yōu)雅的書寫CSS

    這篇文章主要介紹了如何用react優(yōu)雅的書寫CSS,幫助大家更好的理解和學(xué)習(xí)使用react,感興趣的朋友可以了解下
    2021-04-04
  • React中獲取數(shù)據(jù)的3種方法及優(yōu)缺點(diǎn)

    React中獲取數(shù)據(jù)的3種方法及優(yōu)缺點(diǎn)

    這篇文章主要介紹了React中獲取數(shù)據(jù)的3種方法及優(yōu)缺點(diǎn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • React中redux的使用詳解

    React中redux的使用詳解

    Redux 是一個狀態(tài)管理庫,它可以幫助你管理應(yīng)用程序中的所有狀態(tài),Redux的核心概念之一是Store,它表示整個應(yīng)用程序的狀態(tài),這篇文章給大家介紹React中redux的使用,感興趣的朋友一起看看吧
    2023-12-12
  • react 不用插件實(shí)現(xiàn)數(shù)字滾動的效果示例

    react 不用插件實(shí)現(xiàn)數(shù)字滾動的效果示例

    這篇文章主要介紹了react 不用插件實(shí)現(xiàn)數(shù)字滾動的效果示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04

最新評論