中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

react-router?v6怎么實現動態路由

發布時間:2022-08-18 09:17:51 來源:億速云 閱讀:543 作者:iii 欄目:開發技術

這篇文章主要講解了“react-router v6怎么實現動態路由”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“react-router v6怎么實現動態路由”吧!

思路

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

流程如下

  • 用戶登錄成功

  • 獲取用戶權限列表

  • 獲取用戶導航菜單列表

  • 根據權限和導航生成路由表

實現動態路由

router/index.ts 默認路由

import { lazy } from "react";
import { Navigate } from "react-router-dom";
// React 組件懶加載
// 快速導入工具函數
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" />;
};
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! 的標識每次導航列表更新時,再觸發路由更新action

handelFilterRouter 就是根據導航菜單列表 和權限列表 得出路由表的

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";
// 獲取導航菜單列表
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 });
// 更新導航菜單
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 工具函數處理

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

每個后臺的數據返回格式都不一樣,需要自己去轉換,我這里的轉換僅供參考。ps:defaulyRoutes和默認router/index.ts導出是一樣的,可以做個小優化,復用起來。

import { lazy } from "react";
import { Navigate } from "react-router-dom";
// 快速導入工具函數
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"),
  },
];
// 權限列表 和 導航菜單 得出路由表 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 成對應組件
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);
  // 監聽路由表改變重新渲染
  useEffect(() => {
  // deepCopy 深拷貝state數據 不能影響到store里的數據!
  // handelFilterElement 映射對應組件
  // handelEnd 將路由表嵌入默認路由表得到完整路由表
    const end = handelEnd(handelFilterElement(deepCopy(routs)));
    setrout(end);
  }, [routs]);
  return <div className="height-all">{element}</div>;
}
export default App;

感謝各位的閱讀,以上就是“react-router v6怎么實現動態路由”的內容了,經過本文的學習后,相信大家對react-router v6怎么實現動態路由這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

湄潭县| 盐亭县| 岑溪市| 洛南县| 如皋市| 宜州市| 屏东县| 裕民县| 茶陵县| 汉源县| 垦利县| 新安县| 法库县| 铜川市| 磴口县| 堆龙德庆县| 武冈市| 伊宁市| 龙泉市| 永善县| 朝阳县| 雷州市| 绵竹市| 花垣县| 马龙县| 囊谦县| 佳木斯市| 万安县| 彭州市| 台江县| 尖扎县| 西乡县| 双柏县| 十堰市| 安吉县| 太湖县| 奈曼旗| 海城市| 洛隆县| 信丰县| 三都|