总体思路:
1.首先:需要清楚有控权和不控权之分,limitConfig是在modal中定的的一个变量,该变量为true时,表示控权的,就需要对普通用户和vip进行角色的判断。如果值为false,则不论是普通用户还是vip,都能查看,这个一般用于本地调试时候用。
2.其次:要知道有普通用户和vip的角色之分,当limitConfig为true时,就说明已经启动控制权限,则就需要对角色进行判断。以下数据的label以‘三级’开头的对象所在的数组,则为三级菜单数组,show是一个控制这一个菜单是否要展示的变量,如果show=true,表示这个菜单能展示。但是能展示是能展示,最终能不能让用户看到,决定权还是limit和isShowTwo方法及renderSubMenuPop方法中的isShowMenu的值。(isShowMenu在下面的第3点的isShowTwo方法中有提到)
3.在判断的时候,要把所有的情况都考虑到,如果发现控制的条件过多,则可以换一种思路想,找到其的对立面,或者找到只需要满足一个条件,菜单就会出现,那么就控制这个条件能满足即可,其他的情况只要能满足最容易满足的一个,就都能满足菜单显示的条件。
1.后台返回的数据如下:
navMenuInfo: {
'一级菜单A': {
key: 'subMenu4',
label: '一级菜单A',
show: true,
menu: [
{
key: 'subMenu10_',
label: '二级菜单A_1',
show: true,
menu: [{ key: 'subMenu10_1', label: '三级菜单A_1_1', show: false, limit: true, }]
},
{
key: 'subMenu16_',
label: '二级菜单A_2',
show: true,
menu: [
{ key: 'subMenu16_1', label: '三级菜单A_2_1', show: true, limit: true },
{ key: 'subMenu16_2', label: '三级菜单A_2_1', show: true, limit: true },
]
},
{
key: 'subMenu17_',
label: '二级菜单A_3',
show: true,
menu: [
{ key: 'subMenu17_1', label: '三级菜单A_3_1', show: true, limit: true },
]
},
],
itemMenu: [
{ key: 'subMenu10_1', label: '三级菜单A_1_1', show: true },
{ key: 'subMenu16_1', label: '三级菜单A_2_1', show: true },
{ key: 'subMenu16_2', label: '三级菜单A_2_1', show: true },
{ key: 'subMenu17_1', label: '三级菜单A_3_1', show: true },
]
},
2. 在页面中定义的数据结构如下:
this.state = {
src: '',
navMenu: [
{
showPopUp: true,
key: 'subMenu1',
title: '一级菜单A'
},
{
showPopUp: true,
key: 'subMenu2',
title: '一级菜单B'
},
]
}
3.逻辑结构
(1)isShowOne()这个方法用于控制一级菜单的显示和隐藏
render() {
// navMenuInfo: 在modal中自己定义的假数据,模仿后台返回得到的。
// limitConfig: 控制权限的开关,为true时,说明权限启动,只有指定的vip才能看到;为false时,所有人都能看到(如:vip和普通用户)
const { huang: { navMenuInfo, limitConfig } } = this.props
const { navMenu } = this.state
return (
<div>
<hr />
<div className='menu-demo'>
<Menu mode='horizontal' StaticPopOutImageUrl={false}>
{
navMenu.map(item => (
!limitConfig || (limitConfig && item.showPopUp && this.isShowOne(navMenuInfo[item.title]).dataShow) ?
//第1级菜单名称:是<SubMenu/>中的title={item.title}
<SubMenu key={item.key} title={item.title} popup={true}>
{this.renderSubMenuPop(navMenuInfo[item.title].menu)}
</SubMenu>
:
<SubMenu key={item.key} title={item.title} selectable={false} popup={false} >
</SubMenu>
))
}
</Menu>
</div>
<hr />
</div>
)
}
(2)renderSubMenuPop()这个方法用于显示一级菜单下的二级和三级菜单
renderSubMenuPop = (navList) => {
const { huang: { limitConfig, limitUsers } } = this.props
const isShowMenu = limitUsers.findIndex(item => item == 'vip') > -1
return (
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
{
navList.map(item => (
(!limitConfig || (limitConfig && item.show && this.isShowTwo(item))) &&
<div>
<p>{item.label}</p>
{
item.menu.map(itm =>
!limitConfig || (limitConfig && itm.show && (itm.limit ? isShowMenu : true)) ?
<MenuItem key={itm.key}>{itm.label}</MenuItem> : null
)
}
</div>
))
}
</div>
)
}
(3)isShowTwo()这个方法用于控制二级菜单的显示和隐藏
isShowTwo = (item) => {
const { huang: { limitConfig, limitUsers } } = this.props
// isShowMenu:用于判断该用户是否在limitUsers数组(即vip数组的白名单内);
// 补充:这里是简写了,因为是前端模拟,没有一个获取本地用户的接口,事实上‘my’是本地用户的oa账号。所以严格来说isShowMenu应为(其中userInfo是获取本地用户信息接口得到的数据): const isShowMenu = limitUsers.findIndex(item => item == userInfo.oa) > -1
const isShowMenu = limitUsers.findIndex(item => item == 'my') > -1
// 首先,判断2级菜单的show是否为true,如果为false,则从这里就可以判断该2级菜单不显示, 可以直接return结束。
// 但是如果2级菜单的show为true,则需要继续判断3级菜单,因为还需要进一步判断3级菜单是否能支撑2级菜单显示,如果3级都没有一个能显示的,那2级就可以不显示了。
if (item.show) { //如果二级菜单isShow为true,则才继续判断3级的isShow和limit是否
let isSh = false
item.menu.map(m => {
console.log(999999, m.show && (m.limit ? isShowMenu : true));
// 3级的判断思路:2级的show为true之后,继续判断3级。需要遍历3级菜单,如果3级菜单里,只要有一个元素的show为true,对应的limit也为true(limit为true时,代表的是vip用户能看到),并且此时的用户刚好是vip用户,那么这个2级菜单是要进行显示,所以limit为true时,要看该用户是否为VIP,isShowMenu为true代表用户是vip,就能看到。如果limit为false,则表示该3级菜单不论是普通用户还是vip用户,都能看到。
if (m.show && (m.limit ? isShowMenu : true)) {
isSh = true
return
}
})
if (isSh) return item.label
return
} else {
return
}
}
4.最终得到的结果如下:(一级菜单B的弹框小三角样式还未去掉,只写了主要思路,后续在继续完善)