腿夹腿,带你用 react 撸后台,系列三(布局和鉴权篇)(最近有一大波更新) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
爱意满满的作品展示区。
zhangfg

腿夹腿,带你用 react 撸后台,系列三(布局和鉴权篇)(最近有一大波更新)

  •  
  •   zhangfg Nov 6, 2024 2067 views
    This topic created in 537 days ago, the information mentioned may be changed or developed.

    Github 地址 | 文档 | 在线预览 | 主题版在线预览

    react-antd-console 是一个后台管理系统的前端解决方案,封装了后台管理系统必要功能(如登录、鉴权、菜单、面包屑、标签页等),帮助开发人员专注于业务快速开发。项目基于 React 18Ant design 5ViteTypeScript 等新版本。对于使用到的各项技术,会被持续更新至最新版本。可放心用于生产环境

    为了方便大家更好的掌握和使用本项目,推出系列文章:

    • 腿夹腿,带你用 react 撸后台,系列一( Vite 篇)
    • 腿夹腿,带你用 react 撸后台,系列二(项目骨架篇)
    • 腿夹腿,带你用 react 撸后台,系列三(布局和鉴权篇)

    如果你喜欢这个项目或认为对你有用,欢迎使用体验和 Star

    1. 概述

    上篇我们提到使用一个配置 routesConfig,可以生成 reactRoutesroutes,利用 reactRoutes 可生成路由,利用 routes 可生成菜单/面包屑等数据。本篇再来看看,路由、布局、菜单、权限、鉴权等相互是怎么发生化学反应的

    2. 布局组件 Consoleayout

    react-router 中,利用 nested-routes 特性,父组件可作为布局组件。如果在布局组件中使用 <Outlet />,那么当页面 url 匹配到路由配置的 path时,就会渲染对应的路由配置的 component 组件,而布局组件中的其他元素会一直保持不变,并且不会重新渲染

    // src/router/config/index.tsx { path: '/', component: () => import('@/layouts/ConsoleLayout'), // 使用 import() 作代码分割 flatten: true, // flatten 可以将子路由的菜单层级提升到本级,在渲染菜单时有用 children: [ { path: 'index', component: () => import('@/pages/home'), name: '首页', permission: 'homeIndex', icon: <SvgIcon name="home" />, } ], } 
    // src/layouts/ConsoleLayout/index.tsx import { Outlet } from 'react-router-dom'; const COnsoleLayout= () => { return ( <div className="console-layout"> <div className="console-layout__left-side"> <SideMenu /> </div> <div className="console-layout__right-side"> <Header /> <div className="console-layout__right-side-main"> <Outlet /> </div> <Footer /> </div> </div> ); }; 

    再稍微写点样式,就可以写好整体的布局结构了

    3. 保持登录状态和获取权限数据

    话分两头。在登录时, token 被保存在了 localstorage,这样刷新页面后,程序仍然可以读取到保存的 token,因此保持了登录状态。另一方面,只要进入页面就会调用一次用户基本信息接口,其返回了代表用户路由访问权限的数据 permissions。再把后端的数据映射为前端的数据,保存在全局数据中。为方便查询,使用 Set 数据结构

    // src/models/withAuth/permissions.ts function formatPermissions(permissions: string[]) { const set = new Set(permissions); return { homeIndex: set.has('home:index'), // 每一个权限和每一个路由配置,一一对应 }; } export default formatPermissions; 

    4. 菜单组件 <SideMenu />

    antd 有 菜单组件 Menu: Menu 组件可以根据 items 等 api 生成菜单。可以利用权限数据 permissions 和路由配置 routesConfig,生成 items。没有权限的路由,将不包含在 items

    5. 鉴权

    前面我们搭建好了基本的布局结构,但这还不够。还需要在每次切换路由(需要鉴权的路由)的时候,检查登录状态和是否有当前路由访问权限。具体表现为:

    • 每次路由切换,都会检查是否有本地 token ?
      • 若无本地 token ,则跳转登录页;
      • 若有本地 token ,则检查是否已请求基础数据?
        • 若未请求基础数据,则请求之;
        • 若已请求基础数据,则根据基础数据检查是否具备当前路由的访问权限?
          • 若无权限,则去 403 页。
          • 若有权限,则渲染路由 <Outlet />
    withAuthModel.init = () => { // 检查 token const { accessToken } = lsGetToken({ bellwether: true }) ?? {}; if (!accessToken) { this.setState({ hasToken: false, loading: false, }); history.push(`/login`); return; } this.setState({ hasToken: true }); // 检查基础数据 try { if (!this.state.hasRequestedBaseInfo) { await this.requestBaseInfo(); } } catch (err) { console.log(err); } this.setState({ loading: false }); // 检查当前路由的访问权限 const routePath = router.getRoutePath(window.location.pathname); const route = router.flattenRoutes.get(routePath); if (route?.permission && !this.state.permissions[route.permission]) { history.push('/no-access'); } } 

    上述逻辑如果在 vue 中,可以利用 vue-router 的导航守卫功能封装。在 react 可以通过 useEffect 监听 location.pathname 封装。再把这些逻辑放到一个高阶组件 withAuth 中,用 withAuthConsoleLayout 布局组件包裹

    const withAuth = (Component) => { const Auth = (props) => { const loading = useModel(withAuthModel, 'loading'); const location = useLocation(); useEffect(() => { (async function() { await withAuthModel.init(); })(); }, [location.pathname]); if (loading) { return <Loading />; } return ( <Component {...props} /> ); }; return Auth; }; 
    const WithAuthCOnsoleLayout= withAuth(() => { return <ConsoleLayout />; }); 

    也可以编写自定义的布局组件,然后用 withAuth 高阶组件包裹,以达到鉴权效果

    通过以上一顿操作,我们不仅实现了功能,还将配置数据布局/菜单样式鉴权等逻辑解耦。

    6. 系列文章

    • 腿夹腿,带你用 react 撸后台,系列一( Vite 篇)
    • 腿夹腿,带你用 react 撸后台,系列二(项目骨架篇)
    • 腿夹腿,带你用 react 撸后台,系列三(布局和鉴权篇)

    如果你喜欢这个项目或认为对你有用,欢迎使用体验和 Star

    Github 地址 | 文档 | 在线预览 | 主题版在线预览

    2 replies    2024-11-12 16:47:18 +08:00
    Rehtt
        1
    Rehtt  
       Nov 8, 2024 via Android
    之前是手摸手,现在是腿夹腿了
    zhangfg
        2
    zhangfg  
    OP
       Nov 12, 2024
    @Rehtt 只要内容够硬,姿势都不是问题
    About     Help     Advertise     Blog     API     FAQ     Solana     1217 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 40ms UTC 17:52 PVG 01:52 LAX 10:52 JFK 13:52
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86