antd pro4-(3)从服务器请求菜单

本文介绍如何在Ant Design Pro中实现动态菜单和权限控制,通过后端返回用户菜单,避免前端硬编码权限,确保权限的灵活性与安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考官网 路由和菜单

antd pro中默认菜单根据路由配置,匹配登录用户的权限进行生成。
路由节点需要配置authority属性来辅助生成菜单,如:

{
	path: '/admin',
    name: 'admin',
    icon: 'crown',
    component: './Admin',
    authority: ['admin'],
},

考虑到需要比较灵活的配置权限角色,避免增加或修改角色权限后需要更改前端,
所以通过后端返回各用户的菜单。

路由中不写死权限的话,假如用户没有admin权限,使用/admin也可以访问到不在菜单中的页面,但获取业务数据等请求本身后端也会校验权限返回错误,前端处理异常后会跳转到403页面,不知道是不是有更好的方法。

从服务器请求菜单,官网中是这么说明的:

你可以在 src/layouts/BasicLayout.tsx 中修改 menuDataRender,并在代码中发起 http 请求,只需服务器返回下面格式的 json 即可
注意: path 必须要在 config.ts 中定义。(约定式路由不需要,只需页面真实有效即可)
注意: 如果没有选用 typescript,config.js 中菜单的嵌套写法,需要把 “children” 换成 “routes”

[
  {
    "path": "/dashboard",
    "name": "dashboard",
    "icon": "dashboard",
    "children": [
      {
        "path": "/dashboard/analysis",
        "name": "analysis"
      },
      {
        "path": "/dashboard/monitor",
        "name": "monitor"
      },
      {
        "path": "/dashboard/workplace",
        "name": "workplace"
      }
    ]
  }
  // ....
]

冲冲冲…
先写个mock方便测试~~mock/menu.js:

export default {
  'GET /api/currentMenu': [
    {
      path: '/welcome',
      name: 'welcome',
      icon: 'smile',
    },
    {
      path: '/admin',
      name: 'admin',
      icon: 'crown',
    },
    {
      path: '/list',
      name: 'list.table-list',
      icon: 'table',
    },
  ],
}

继续写个model来发起请求和变更state~~models/userMenu.js:

import {queryCurrentMenu} from "@/services/user";

const UserMenuModel = {
  namespace: 'userMenu',
  state: {
    currentMenu: [],
  },
  effects: {
    //代表事件的Action对象,由于函数体不需要Action内容,所有使用`_`占位符代替Action对象了
    //const { call, put } = sagaEffects
    //也可以yield call(request, url), 这里统一放到services
    *fetchCurrentMenu(_, { call, put }) {
      const response = yield call(queryCurrentMenu);
      yield put({
        type: 'saveCurrentMenu',
        payload: response,
      });
    },
  },
  reducers: {
    saveCurrentMenu(state, action) {
      return { ...state, currentMenu: action.payload || [] };
    },
  },
}
export default UserMenuModel;

在service加点代码~~services/user.js:

export async function queryCurrentMenu() {
  return request('/api/currentMenu');
}

接下来就是调整下BasicLayout了:

调整一下connect 的mapStateToProps, 使从model中注入props

export default connect(({ global, settings, userMenu }) => ({
  collapsed: global.collapsed,
  settings,
  menuData: userMenu.currentMenu,
}))(BasicLayout);

用useEffect发送Action,因为BasicLayout是属于函数组件非类组件,没有生命周期函数如componentDidMount()等;
从props取出menuData;
变更menuDataRender;
实现如下:

const BasicLayout = props => {
  const {
    ...
    menuData,
  } = props;
  /**
   * constructor
   */
  useEffect(() => {
    if (dispatch) {
      dispatch({
        type: 'userMenu/fetchCurrentMenu',
      });
    }
  }, []);
  ...
  render(
  	...
  	menuDataRender={() => menuData}
  	...
  )
};

运行瞅瞅
菜单正常显示了,图标没显示出来!
Console这样提示

为了兼容 antd@4,我们会在下个版本删除配置 icon: string 生成icon的用法。请查看
https://pro.ant.design/blog/antd-4.0-cn 寻找解决方式!

查看后是这么说的:

但是 Pro 中支持通过设置 icon 配置菜单图标,在 4.0 中将无法得到支持,所以我们提供了相应的插件来保留此功能。
使用方式如下 :
yarn add umi-plugin-antd-icon-config -D
并且在 config.ts 中设置

export default {
  plugins: [['umi-plugin-antd-icon-config', {}]],
};

我使用的是npm,相当于

npm install umi-plugin-antd-icon-config --save-dev

添加依赖会更新 package.json
–dev 依赖会记录在 package.json 的 devDependencies 下

然后,,图标还是没出来。。
怀疑是不是环境问题,依赖的包版本哪里不对可能。先这样吧。

### 实现Ant Design Pro自定义菜单结构 在Ant Design Pro中,可以通过多种方式来定制菜单结构。通常情况下,在`app.tsx`文件内完成菜单配置可以满足大部分需求[^3]。 #### 修改`app.tsx` 为了创建自定义菜单结构,可以在项目的入口文件之一——`app.tsx`中修改默认的菜单项: ```typescript import { ConfigProvider } from &#39;antd&#39;; import React from &#39;react&#39;; const menuData = [ { name: "首页", icon: "home", path: "/welcome" }, { name: "用户管理", icon: "team", path: "/users", children: [ { name: "查询用户", path: "/users/search" }, { name: "新增用户", path: "/users/add" } ] } ]; export default () => ( <ConfigProvider> {/* 使用menuData作为数据源 */} </ConfigProvider> ); ``` 上述代码片段展示了如何通过调整`menuData`数组来自定义顶层以及子级菜单条目。每个对象代表一个单独的菜单项,并允许指定名称、图标和路径属性;对于具有下拉列表形式的复杂菜单,则可通过children字段添加更多层次的内容。 #### 动态加载菜单 如果希望基于某些条件动态生成这些菜单链接,比如从服务器获取最新的权限信息后再决定显示哪些选项给当前登录者查看的话,那么就需要利用React的状态管理和生命周期方法了。下面是一个简单的例子说明怎样做到这一点: ```javascript import { useEffect, useState } from &#39;react&#39;; import request from &#39;@/utils/request&#39;; // 假设这是封装好的HTTP请求工具函数库 function App() { const [menus, setMenus] = useState([]); useEffect(() => { async function fetchMenu(){ try{ let response = await request(&#39;/api/getUserPermissions&#39;); setMenus(response.data.menus || []); }catch(error){ console.error(&#39;Failed to load menus&#39;, error); } } fetchMenu(); },[]); return( <> {/* 渲染menus变量中的内容为实际可见的导航栏 */} </> ); } ``` 这段脚本会在组件首次渲染时发起一次异步调用来取得用户的访问控制列表(ACL),并将结果保存至状态机内部以便后续操作使用。这样就可以确保只有当API返回有效响应之后才会更新界面上所呈现出来的菜单布局。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值