react路由权限v6

方法

1.模拟vue的路由拦截(未尝试)
2.进入页面拦截(模拟后台管理系统)

route v6常用属性

image

页面梳理

  • 路由表
  • 公共路由
  • 权限路由
  • layout(+权限判定)
  • 登录

页面布局

image

路由表

点击查看代码

//menus.js
const menus = [
  {
    key: "0-0",
    path: "/list",
    title: "系统首页",
    icon: <AreaChartOutlined />,
    component: React.lazy(() => import("../pages/List.jsx")),
  },
  {
    key: "0-1",
    path: "/edit",
    title: "修改",
    icon: <AreaChartOutlined />,
    children: [
      {
        key: "0-1-0",
        path: "/edit/car",
        title: "文章修改",
        icon: <AreaChartOutlined />,
        children: [
          {
            key: "0-1-0-0",
            path: "",
            title: "列表",
            hidden:true,
            icon: <AreaChartOutlined />,
            component: React.lazy(() => import("../pages/Edit.jsx")),
          },
          {
            key: "0-1-0-1",
            path: "/edit/car/add",
            title: "新增",
            hidden:true,
            icon: <AreaChartOutlined />,
            component: React.lazy(() => import("../pages/Edit.jsx")),
          },
        ]
      },
      {
        key: "0-1-1",
        path: "/edit/ship",
        title: "文章发布",
        icon: <AreaChartOutlined />,
        component: React.lazy(() => import("../pages/Means.jsx")),
      }
    ]
  },
  {
    key: "0-2",
    path: "/means",
    title: "资料",
    icon: <AreaChartOutlined />,
    component: React.lazy(() => import("../pages/Means.jsx")),
    children: [
      {
        key: "0-2-0",
        path: "/means/ship",
        title: "资料查看",
        icon: <AreaChartOutlined />,
        component: React.lazy(() => import("../pages/Repbox.jsx")),
      }
    ]
  },
]

export default menus;

公共路由

layout与权限判定放在App页面
注意:v6嵌套路由匹配严格,加上/*全匹配

//main.js 放入公共路由组件
import { BrowserRouter as Router, Routes, Route} from "react-router-dom";
<Router>
    <Routes>
      <Route path="/*" element={<App />}></Route>
      <Route path="/login" element={<Login />}></Route>
      <Route path="/register" element={<Register />}></Route>
    </Routes>
</Router>

权限路由

加载时只匹配页面加载且懒加载,故单独写一个jsx,使用Suspense+Lazy

//component加载方式:element={<item.component />}
const renderRoute = (menus) => {
  return menus.map((item) => {
    if (item.children) {
      return (
        <Route path={item.path} key={item.key}>
          {renderRoute(item.children)}
        </Route>
      );
    } else {
      return (
        <Route
          path={item.path}
          key={item.key}
          element={<item.component />}
        ></Route>
      );
    }
  });
};

重定向/

const renderRedirect = (menus) => {
    return <Route path="/" element={<Navigate to={menus[0].path} />}></Route>;
};

权限通过props获取,

export default function AppMain(props) {
  const {menus}=props
  return (
    <Suspense fallback={<h2>loading...</h2>}>
      <Routes>
        {renderRoute(menus)}
        {renderRedirect(menus)}
        <Route path="*" element={<NotFound />} />
      </Routes>
    </Suspense>
  );
}

layout(+权限判定)< app >

//过滤路由meun:在登录获取的菜单权限
  const Validation = (menus, meun) => {
    return menus.filter((item) => {
      if (item.children) {
        item.children = Validation(item.children, meun);
      }
      return meun.includes(item["key"]);
    });
  };

token监听

const [state, setState] = useState(false);//判断进入与否页面
const [fmenus, setFmenus] = useState([]);//菜单
const navigate = useNavigate();
useEffect(() => {
  getPassword().then((res) => {
     //判断token
    if (判断通过) {
    //登录时保存在localStorage的菜单权限或者后端查询角色权限
    //meun为一个数组数据
      const meun = localStorage.getItem("meun");
      if (meun.includes("all")) {//all拥有所有权限,基础版逻辑
        setFmenus(menus);
      } else {
        let meunsList=deepCopy(menus)//深拷贝
        setFmenus(Validation(meunsList, meun));
      }
      setState(true);
    } else {
      navigate('/login')
      setState(false);
    }
  });
}, [localStorage.getItem("token")]);

过滤好的菜单传递给AppMain:权限路由;Asider:侧边栏

return (
  <>
    {state ? (
      <Layout id="app">
        <Header />
        <Layout>
          <Asider menus={fmenus} />
          <Content>
            <BreadCrumbs></BreadCrumbs>
            <AppMain menus={fmenus}></AppMain>
            {/* <Outlet></Outlet> */}
          </Content>
        </Layout>
        <footer>Respect | Copyright &copy;2022 Author 曜炘</footer>
      </Layout>
    ) : null}
  </>
);

登录与退出登录

//登录时存储数据
 localStorage.setItem("username", username);
 localStorage.setItem("token", token);
 localStorage.setItem("meun", meun);
 //退出登录时清空数据
 localStorage.clear();
 sessionStorage.clear();
posted @ 2022-09-14 14:02  流云君  阅读(1220)  评论(0编辑  收藏  举报