ant-design-pro 動態菜單-路由詳解
最近利用ant-design-pro開發項目要實現之前的項目嵌入到新項目里來,並且根據和后台的接口返回的數據顯示側邊欄菜單。既然是是利用別人的架構那當然是從文檔中找實現的方法,終於不負苦心人在https://pro.ant.design/docs/router-and-nav-cn文檔那里找到初步的解決方法
進入src/layouts/Basilayout.js在官網中直接復制該代碼,將原文件替換。
現在正式進入正題。
1,在src/layouts/Basilayout.js中利用connect與拉取菜單的models建立聯系
我的是放在views的models下面所以代碼如下
export default connect(({global, setting, views }) => ({
collapsed: global.collapsed,
layout: setting.layout,
…setting,
…views,
}))(BasicLayout);
2,在src/layouts/Basilayout.js中的生命周期函數componentDidMount里面調用拉取菜單的接口,
componentDidMount() {
const { dispatch } = this.props;
dispatch({
type: ‘views/fetch’,
});
}
我調取的是下面views.js里面的effects的fetch方法
至於model里面怎么寫可以看官方文檔https://pro.ant.design/docs/server-cn
這里是我寫的一個views的model —(下面代碼的關鍵字是getMenuMapArrData )
import { getMenuList } from '@/services/api'
import { getMenuSessionData, getMenuMapArrData } from '@/utils/utils.js'
export default {
namespace: 'views',
state: {
datas: [],
urlValues: 'https://boss.icarbonx.com/lims-ui/baselab/qcPaths/exception',
urlDatas: [],
},
effects: {
*fetch({ payload }, { call, put }) {
const response = yield call(getMenuList, payload);
console.log(response,'得到列表')
yield put({
type: 'save',
payload: response
})
},
*changeurl({ payload }, { call, put }){
yield put({
type: 'change',
payload: payload
})
},
},
reducers: {
save(state, action) {
return {
...state,
datas: getMenuMapArrData(action.payload),
urlDatas: getMenuSessionData(action.payload),
}
},
change(state, action) {
return {
...state,
urlValues: action.payload,
}
},
}
}
3、getMenuList菜單接口返回的格式化,當然有些老鐵直接就按照router.config.js的形式寫的但是有些情況是后台人員返回的數據並不是這樣這就需要我們格式化。
理想情況返回的數據是
[{
path: '/user',
component: '../layouts/UserLayout',
routes: [
{ path: '/user', redirect: '/user/login' },
{ path: '/user/login', component: './User/Login' },
{ path: '/user/register', component: './User/Register' },
{ path: '/user/register-result', component: './User/RegisterResult' },
],
}]
**現實情況返回的:**
**[
{
"id": "dashboardws",
"name": "Dashboard",
"description": "Dashboard",
"url": 'https://boss.xxx.com/qcScheme/qcPrograms',
component: './View/home',
"children": []
},
{
"id": "knowledge",
"name": "Knowledge Platform",
component: './View/home',
"url": null,
"children": [
{
"id": "gene",
"name": "Gene",
component: './View/home',
"url": 'https://XXX.XXX.com/qcPaths/qualityProjectQuery',
"children": null
},
{
"id": "phenotype",
"name": "Phenotype",
component: './View/home',
"url": 'https://XXX.XXX.com/lims-ui/baselab/qcPaths',
"children": null
},
{
"id": "microbes",
"name": "Microorganism",
component: './View/home',
"url": 'https://boss.xxx.com/qcPaths/qcSamplesCheck',
"children": null
}
]
},
{
"id": "indicatorww",
"name": "Index Platform",
"url": 'https://baidu.com',
"children": []
},
{
"id": "report",
"name": "Report Platform",
"url": 'https://boss.xxx.com/limb/qcScheme/qcSamples',
"children": []
}
]
這樣的話不能直接用要先處理,我的話是通過utils.js里寫一個名叫getMenuMapArrData的方法進行格式化將后台返回的數據處理成類似理想狀態的格式,
類似於 —(下面代碼的關鍵字是routes)
const menuListData = [
{
"id": "knowledge",
"name": "Knowledge Platform",
component: './View/home',
"url": null,
"routes": [
{
"id": "gene",
"name": "Gene",
component: './View/home',
"url": 'https://XXX.XXX.com/qcPaths/qualityProjectQuery',
"children": null
},
{
"id": "phenotype",
"name": "Phenotype",
component: './View/home',
"url": 'https://XXX.XXX.com/lims-ui/baselab/qcPaths',
"children": null
},
{
"id": "microbes",
"name": "Microorganism",
component: './View/home',
"url": 'https://boss.xxx.com/qcPaths/qcSamplesCheck',
"children": null
}
]
},
]
主要是你格式化的這里里面要有routes這個屬性,系統才能識別出你的菜單,當然沒有子級菜單可以不需要改。
4、需要在router.config.js里面把你的菜單全集寫出來。你動態拉取的必須是你router.config.js里面有的路由才能有效。
5、我那里是通過iframe嵌套一些頁面所以我在寫router.config.js的路由規則時我用到了動態路由的配置
即在router.config.js
{
path: ‘/:post’,
component: ‘./View/home’,
},
{
path: ‘/:post/:id’,
component: ‘./View/home’,
},
經過我的實驗這個要寫在
{
component: ‘404’,
},
的前面才不會被404 重定向
6、在src/layouts/Basilayout.js中獲取處理后的菜單列表數據,在render()函數里面const menuData = this.getMenuData()這句,調取getMenuData方法,這里面通過this.props動態獲取到datas,datas就是我處理后的菜單數據。
注意:如果原數據不是理想數據而又不處理,而是在這個getMenuData里處理,會發生一些意想不到的錯誤。
getMenuData() {
const {
datas,
route: { routes },
} = this.props;
const newRoutes = [...datas, ...routes]
return memoizeOneFormatter(Array.from([...newRoutes]));
}
7、至此就結束了應該就可以完成了