想异步加载左侧菜单的数据,怎么实现呢?
你可以在 src/layouts/BasicLayout.js 中修改 getMenuData 的来源,不从config中获取,使用动态的数据,但要注意:
使用高阶组件 把BasicLayout 包一层 请求数据 然后传下来就可以了 然后 跟着 @ddcat1115 弄
能给个示例代码吗,各位大神
1.先创建高阶组件App
import React from 'react';
import {connect} from "dva";
import {Spin} from "antd";
const App = (WrappedComponent) => {
@connect(state => ({
global: state.global,
}))
class App extends React.Component {
componentDidMount() {
this.props.dispatch({
type: 'global/fetchMenus'
})
}
render() {
const menus = this.props.global.menus;
return (
menus.length === 0 ? <Spin spinning={true}/>:
<WrappedComponent {...this.props} menus={menus}/>
)
}
}
return App;
};
export default App;
2.然后再BasicLayout上添加@App注解
大神,可不可以再看一下BasicLayout的代码
// 省略之前所有
@App
export default class BasicLayout extends React.Component {
//省略剩下所有
最后是这样吗?
export default connect(state => ({
currentUser: state.user.currentUser,
collapsed: state.global.collapsed,
fetchingNotices: state.global.fetchingNotices,
notices: state.global.notices,
}))(BasicLayout);
关注此问题。
怎么构建符合要求的菜单??
现在报错:Uncaught (in promise) Error: Cannot find module 'function DynamicComponent() {
//。。。。。。。
const list = [
{
name: '基础管理4444data',
path: 'baseData',
icon: 'check-circle-o',
children: [
{
name: '考试数据管理',
path: 'examData',
model: 'exam',
component: './routes/BaseData/ExamData',
},
{
name: '准考证数据管理',
path: 'licenseData',
model: 'license',
component: './routes/BaseData/LicensesData',
},
],
}];
const arr = list.map((item) => {
item.children.map((obj) => {
obj.component = dynamicWrapper(app, [obj.model], () => import(obj.component));
return obj;
});
return item;
});
const navData = [
{
component: dynamicWrapper(app, ['user', 'login'], () => import('./layouts/BasicLayout')),
layout: 'BasicLayout',
name: '首页', // for breadcrumb
path: '/',
children: list,
}];_
希望可以改造菜单后端获取,前端不需要配置那么复杂,角色这一概念在前端感觉有点多余,应该来自于后端;初步思路->用户登陆后同步从后端读取菜单信息(即使有一个进度条或等待),页面维度权限也可以也可以在页面初始化的时候异步加载。后端控制起来也容易些,前端小白纯属吐槽,期待二期用于用于正式环境。
如果 router 还是使用 config 中的数据,需要自己配置每个页面的 name,保证面包屑正常(原来的name是从menu中获取)
name可以自己配置, 那authority怎么办, 这个必须从后台获取吧
按照
@
teeemooo的方法报错
TypeError: Object(...) is not a function
我参考这个可以实现
https://github.com/ant-design/ant-design-pro/compare/master...denggy:menus?diff=split&name=menus
菜单不能正常展开怎么弄,点击了就还原了,加了defaultOpenKeys 没用
defaultOpenKeys={['hello']}
defaultSelectedKeys={['hello']}
使用@teeemooo 的方法能实现,除了上述他分享的代码更改,还需要更改SiderMenu的menuData属性,不再使用原来,使用你放到props中的menus(记得formater menus)
有人实现了吗
// 省略之前所有
@App
export default class BasicLayout extends React.Component {
//省略剩下所有
外面包装一层高阶组件,就是在原有组件代码上一行加个高阶组件@App的注释,这个语法没看懂?哪里有相关文档?
另外:
const App = (WrappedComponent) => {
@connect(state => ({
global: state.global,
}))
这个语法也没看懂,按理返回的(只嵌套)是App Compnent这个class(函数),这么返回两行过程代码不会报语法错误吗?
额,这两句是不是传给connect高阶函数的两个参数,返回一个做了绑定的组件??
求解释,谢谢。。
@teeemooo
@App是装饰器
@App
class BasicLayout{}
就是相当于
class BasicLayout{}
App(BasicLayout)
const App = (WrappedComponent) => { @connect(state => ({ global: state.global, }))
这个要连着下面一起看
@connect(state => ({ global: state.global}))
class App extends React.Component {
........
}
上面那个connect(state => ({ global: state.global}))其实应该也是返回一个装饰器
所以
@connect(state => ({
global: state.global,
}))
class App extends React.Component {
.......
}
return App;
意思就是
class App extends React.Component {
.......
}
return connect(state => ({global: state.global }))(App)
应该是这样的意思,搜一下js装饰器就有了
@FatFatFox
@zhang0ZGC 可否再发一遍链接,上一个链接已失效。感谢。
@JevonYang 我也不知道是啥了。。好像是 #1290 的,你看下那个file chnages
根据#1555
src/components/SiderMenu/SiderMenu.js 组件constructor里初始化了this.menus = props.menuData,直接用props.menuData替换this.menu
SiderMenu组件定义了,this.menus = props.menuData,在组件使用的是this.menu,所以如何改变props的值,组件都不会变化。
如果将this.menu替换成props.menuData,菜单数据可以从后台传过来,但是菜单的展开和收缩会出现问题。是不是可以从这个思路来解决这个问题。
我已经实现了动态菜单渲染 后期我会传到我的GitHub
@guoguanrong123
Can you send the PR with your update?
@veeramarni
https://pro.ant.design/docs/router-and-nav#Menu
Follow this link in version 2.0 if you need to request menu from server-end.
If your project does not require a menu, you can remove the mount of the SiderMenu component directly in BasicLayout. And set const MenuData = [] in src/layouts/BasicLayout.
If you need to request a menu from the server, you can set menuData to state. Then the status is modified by the network acquisition.
@JevonYang I don't see how to generate dynamic menu as explained in https://github.com/ant-design/ant-design-pro/issues/1895
@veeramarni
the author is very lazy ,follow this :
src/layouts/BasicLayout.js :
getMenuData() {
# const {
# route: { routes },
# } = this.props;
//console.log(route) to get router.config's Json Array
//rewrite it from api with same format before
const route = request.getRoute();
return formatter(routes);
}
@WG-Com
给你一个不推荐的搞法:

2,0异步菜单已经是分分钟的事情了
特别是
91be534a97bcc3400a003ccce0168e66368a3440 这次提交之后
This is the way i implemted it.
First i built a Wrapper:
import React from 'react';
import {connect} from "dva";
import {Spin} from "antd";
import { cloneDeep } from 'lodash';
const FetchRoutes = (WrappedComponent) => {
@connect(state => ({
global: state.global,
}))
class FetchRoutes extends React.Component {
componentDidMount() {
this.props.dispatch({
type: 'global/fetchRoutes'
})
}
render() {
const routes = this.props.global.routes;
var route = cloneDeep(this.props.route)
route.routes = routes
return (
routes.length === 0 ? <Spin spinning={true}/>:
<WrappedComponent {...this.props} route={route} />
)
}
}
return FetchRoutes;
};
export default FetchRoutes;
then i wrapped the components that needed to obtain this information with the Wrapper for instance:
import FetchRoutes from '../wrappers/FetchRoutes';
...
@FetchRoutes
class BasicLayout extends React.PureComponent {.....
Most helpful comment
1.先创建高阶组件App
2.然后再BasicLayout上添加
@App注解