Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
ant-design-pro
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
duanledexianxianxian
ant-design-pro
Commits
a5b5f9c8
Commit
a5b5f9c8
authored
6 years ago
by
杨伟荣
Committed by
陈帅
6 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修复侧边栏菜单不能动态显示的问题
parent
76d8fcbf
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
254 additions
and
0 deletions
+254
-0
src/components/SiderMenu/SiderMenu.js
src/components/SiderMenu/SiderMenu.js
+254
-0
No files found.
src/components/SiderMenu/SiderMenu.js
0 → 100644
View file @
a5b5f9c8
import
React
,
{
PureComponent
}
from
'
react
'
;
import
{
Layout
,
Menu
,
Icon
}
from
'
antd
'
;
import
pathToRegexp
from
'
path-to-regexp
'
;
import
{
Link
}
from
'
dva/router
'
;
import
styles
from
'
./index.less
'
;
import
{
urlToList
}
from
'
../_utils/pathTools
'
;
const
{
Sider
}
=
Layout
;
const
{
SubMenu
}
=
Menu
;
// Allow menu.js config icon as string or ReactNode
// icon: 'setting',
// icon: 'http://demo.com/icon.png',
// icon: <Icon type="setting" />,
const
getIcon
=
icon
=>
{
if
(
typeof
icon
===
'
string
'
&&
icon
.
indexOf
(
'
http
'
)
===
0
)
{
return
<
img
src
=
{
icon
}
alt
=
"
icon
"
className
=
{
`
${
styles
.
icon
}
sider-menu-item-img`
}
/>
;
}
if
(
typeof
icon
===
'
string
'
)
{
return
<
Icon
type
=
{
icon
}
/>
;
}
return
icon
;
};
/**
* Recursively flatten the data
* [{path:string},{path:string}] => {path,path2}
* @param menu
*/
export
const
getFlatMenuKeys
=
menu
=>
menu
.
reduce
((
keys
,
item
)
=>
{
keys
.
push
(
item
.
path
);
if
(
item
.
children
)
{
return
keys
.
concat
(
getFlatMenuKeys
(
item
.
children
));
}
return
keys
;
},
[]);
/**
* Find all matched menu keys based on paths
* @param flatMenuKeys: [/abc, /abc/:id, /abc/:id/info]
* @param paths: [/abc, /abc/11, /abc/11/info]
*/
export
const
getMenuMatchKeys
=
(
flatMenuKeys
,
paths
)
=>
paths
.
reduce
(
(
matchKeys
,
path
)
=>
matchKeys
.
concat
(
flatMenuKeys
.
filter
(
item
=>
pathToRegexp
(
item
).
test
(
path
))),
[]
);
export
default
class
SiderMenu
extends
PureComponent
{
constructor
(
props
)
{
super
(
props
);
this
.
flatMenuKeys
=
getFlatMenuKeys
(
props
.
menuData
);
this
.
state
=
{
openKeys
:
this
.
getDefaultCollapsedSubMenus
(
props
),
};
}
componentWillReceiveProps
(
nextProps
)
{
const
{
location
}
=
this
.
props
;
if
(
nextProps
.
location
.
pathname
!==
location
.
pathname
)
{
this
.
setState
({
openKeys
:
this
.
getDefaultCollapsedSubMenus
(
nextProps
),
});
}
}
/**
* Convert pathname to openKeys
* /list/search/articles = > ['list','/list/search']
* @param props
*/
getDefaultCollapsedSubMenus
(
props
)
{
const
{
location
:
{
pathname
},
}
=
props
||
this
.
props
;
return
getMenuMatchKeys
(
this
.
flatMenuKeys
,
urlToList
(
pathname
));
}
/**
* 判断是否是http链接.返回 Link 或 a
* Judge whether it is http link.return a or Link
* @memberof SiderMenu
*/
getMenuItemPath
=
item
=>
{
const
itemPath
=
this
.
conversionPath
(
item
.
path
);
const
icon
=
getIcon
(
item
.
icon
);
const
{
target
,
name
}
=
item
;
// Is it a http link
if
(
/^https
?
:
\/\/
/
.
test
(
itemPath
))
{
return
(
<
a
href
=
{
itemPath
}
target
=
{
target
}
>
{
icon
}
<
span
>
{
name
}
<
/span
>
<
/a
>
);
}
const
{
location
,
isMobile
,
onCollapse
}
=
this
.
props
;
return
(
<
Link
to
=
{
itemPath
}
target
=
{
target
}
replace
=
{
itemPath
===
location
.
pathname
}
onClick
=
{
isMobile
?
()
=>
{
onCollapse
(
true
);
}
:
undefined
}
>
{
icon
}
<
span
>
{
name
}
<
/span
>
<
/Link
>
);
};
/**
* get SubMenu or Item
*/
getSubMenuOrItem
=
item
=>
{
if
(
item
.
children
&&
item
.
children
.
some
(
child
=>
child
.
name
))
{
const
childrenItems
=
this
.
getNavMenuItems
(
item
.
children
);
// 当无子菜单时就不展示菜单
if
(
childrenItems
&&
childrenItems
.
length
>
0
)
{
return
(
<
SubMenu
title
=
{
item
.
icon
?
(
<
span
>
{
getIcon
(
item
.
icon
)}
<
span
>
{
item
.
name
}
<
/span
>
<
/span
>
)
:
(
item
.
name
)
}
key
=
{
item
.
path
}
>
{
childrenItems
}
<
/SubMenu
>
);
}
return
null
;
}
else
{
return
<
Menu
.
Item
key
=
{
item
.
path
}
>
{
this
.
getMenuItemPath
(
item
)}
<
/Menu.Item>
;
}
};
/**
* 获得菜单子节点
* @memberof SiderMenu
*/
getNavMenuItems
=
menusData
=>
{
if
(
!
menusData
)
{
return
[];
}
return
menusData
.
filter
(
item
=>
item
.
name
&&
!
item
.
hideInMenu
)
.
map
(
item
=>
{
// make dom
const
ItemDom
=
this
.
getSubMenuOrItem
(
item
);
return
this
.
checkPermissionItem
(
item
.
authority
,
ItemDom
);
})
.
filter
(
item
=>
item
);
};
// Get the currently selected menu
getSelectedMenuKeys
=
()
=>
{
const
{
location
:
{
pathname
},
}
=
this
.
props
;
return
getMenuMatchKeys
(
this
.
flatMenuKeys
,
urlToList
(
pathname
));
};
// conversion Path
// 转化路径
conversionPath
=
path
=>
{
if
(
path
&&
path
.
indexOf
(
'
http
'
)
===
0
)
{
return
path
;
}
else
{
return
`/
${
path
||
''
}
`
.
replace
(
/
\/
+/g
,
'
/
'
);
}
};
// permission to check
checkPermissionItem
=
(
authority
,
ItemDom
)
=>
{
const
{
Authorized
}
=
this
.
props
;
if
(
Authorized
&&
Authorized
.
check
)
{
const
{
check
}
=
Authorized
;
return
check
(
authority
,
ItemDom
);
}
return
ItemDom
;
};
isMainMenu
=
key
=>
{
return
this
.
props
.
menuData
.
some
(
item
=>
key
&&
(
item
.
key
===
key
||
item
.
path
===
key
));
};
handleOpenChange
=
openKeys
=>
{
const
lastOpenKey
=
openKeys
[
openKeys
.
length
-
1
];
const
moreThanOne
=
openKeys
.
filter
(
openKey
=>
this
.
isMainMenu
(
openKey
)).
length
>
1
;
this
.
setState
({
openKeys
:
moreThanOne
?
[
lastOpenKey
]
:
[...
openKeys
],
});
};
render
()
{
const
{
logo
,
collapsed
,
onCollapse
}
=
this
.
props
;
const
{
openKeys
}
=
this
.
state
;
// Don't show popup menu when it is been collapsed
const
menuProps
=
collapsed
?
{}
:
{
openKeys
,
};
// if pathname can't match, use the nearest parent's key
let
selectedKeys
=
this
.
getSelectedMenuKeys
();
if
(
!
selectedKeys
.
length
)
{
selectedKeys
=
[
openKeys
[
openKeys
.
length
-
1
]];
}
return
(
<
Sider
trigger
=
{
null
}
collapsible
collapsed
=
{
collapsed
}
breakpoint
=
"
lg
"
onCollapse
=
{
onCollapse
}
width
=
{
256
}
className
=
{
styles
.
sider
}
>
<
div
className
=
{
styles
.
logo
}
key
=
"
logo
"
>
<
Link
to
=
"
/
"
>
<
img
src
=
{
logo
}
alt
=
"
logo
"
/>
<
h1
>
Ant
Design
Pro
<
/h1
>
<
/Link
>
<
/div
>
<
Menu
key
=
"
Menu
"
theme
=
"
dark
"
mode
=
"
inline
"
{...
menuProps
}
onOpenChange
=
{
this
.
handleOpenChange
}
selectedKeys
=
{
selectedKeys
}
style
=
{{
padding
:
'
16px 0
'
,
width
:
'
100%
'
}}
>
{
this
.
getNavMenuItems
(
this
.
props
.
menuData
)}
<
/Menu
>
<
/Sider
>
);
}
}
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment