1
2
3
import Menu from 'ant-design-vue/es/menu'
import Icon from 'ant-design-vue/es/icon'
4
const { Item , SubMenu } = Menu
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
export default {
name : 'SMenu' ,
props : {
menu : {
type : Array ,
required : true
},
theme : {
type : String ,
required : false ,
default : 'dark'
},
mode : {
type : String ,
required : false ,
default : 'inline'
},
collapsed : {
type : Boolean ,
required : false ,
default : false
}
},
29
data () {
30
31
32
33
34
35
36
37
38
39
40
41
42
return {
openKeys : [],
selectedKeys : [],
cachedOpenKeys : []
}
},
computed : {
rootSubmenuKeys : vm => {
const keys = []
vm . menu . forEach ( item => keys . push ( item . path ))
return keys
}
},
43
mounted () {
44
45
46
this . updateMenu ()
},
watch : {
47
collapsed ( val ) {
48
49
50
51
52
53
54
55
56
57
58
59
60
if ( val ) {
this . cachedOpenKeys = this . openKeys . concat ()
this . openKeys = []
} else {
this . openKeys = this . cachedOpenKeys
}
},
$route : function () {
this . updateMenu ()
}
},
methods : {
// select menu item
61
onOpenChange ( openKeys ) {
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// 在水平模式下时执行,并且不再执行后续
if ( this . mode === 'horizontal' ) {
this . openKeys = openKeys
return
}
// 非水平模式时
const latestOpenKey = openKeys . find ( key => ! this . openKeys . includes ( key ))
if ( ! this . rootSubmenuKeys . includes ( latestOpenKey )) {
this . openKeys = openKeys
} else {
this . openKeys = latestOpenKey ? [ latestOpenKey ] : []
}
},
76
updateMenu () {
谭毅彬
authored
12 months ago
77
78
79
// 解决三级菜单缓存及路由问题 start
const routes = this . $route . meta [ 'matched' ] // 新修改,展开菜单问题
const { hidden , selectedKeys } = this . $route . meta
80
if ( routes . length >= 3 && hidden ) {
谭毅彬
authored
12 months ago
81
82
routes . pop ()
this . selectedKeys = selectedKeys
83
} else {
谭毅彬
authored
12 months ago
84
this . selectedKeys = [ routes . pop (). path ]
85
86
87
}
let openKeys = []
if ( this . mode === 'inline' ) {
谭毅彬
authored
12 months ago
88
89
90
routes . forEach ( item => {
openKeys . push ( item . path )
})
91
}
谭毅彬
authored
12 months ago
92
// 解决三级菜单缓存及路由问题 end
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// update-begin-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
// 包含冒号的是动态菜单
if ( this . selectedKeys [ 0 ]. includes ( ':' )) {
let selectedKey = this . $route . fullPath
this . selectedKeys = [ selectedKey ]
let newOpenKeys = []
this . fullOpenKeys ( this . menu , selectedKey , newOpenKeys )
if ( newOpenKeys . length > 0 ) {
openKeys = newOpenKeys . reverse ()
}
}
// update-end-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
//update-begin-author:taoyan date:20190510 for:online表单菜单点击展开的一级目录不对
108
if ( ! this . selectedKeys || this . selectedKeys [ 0 ]. indexOf ( ":" ) < 0 ) {
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
this . collapsed ? ( this . cachedOpenKeys = openKeys ) : ( this . openKeys = openKeys )
}
//update-end-author:taoyan date:20190510 for:online表单菜单点击展开的一级目录不对
},
// update-begin-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
// 递归查找当前选中的菜单和父级菜单,填充openKeys
fullOpenKeys ( menus , selectedKey , openKeys ) {
for ( let item of menus ) {
if ( item . path === selectedKey ) {
openKeys . push ( item . path )
this . $emit ( 'updateMenuTitle' , item )
return true
} else if ( Array . isArray ( item . children )) {
if ( this . fullOpenKeys ( item . children , selectedKey , openKeys )) {
openKeys . push ( item . path )
return true
}
}
}
},
// update-end-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
// render
132
renderItem ( menu ) {
133
134
135
136
137
if ( ! menu . hidden ) {
return menu . children && ! menu . alwaysShow ? this . renderSubMenu ( menu ) : this . renderMenuItem ( menu )
}
return null
},
138
renderMenuItem ( menu ) {
139
140
const target = menu . meta . target || null
const tag = target && 'a' || 'router-link'
141
142
143
let props = { to : { name : menu . name }}
if ( menu . route && menu . route === '0' ) {
props = { to : { path : menu . path }}
144
145
}
146
const attrs = { href : menu . path , target : menu . meta . target }
147
148
149
150
151
152
if ( menu . children && menu . alwaysShow ) {
// 把有子菜单的 并且 父菜单是要隐藏子菜单的
// 都给子菜单增加一个 hidden 属性
// 用来给刷新页面时, selectedKeys 做控制用
menu . children . forEach ( item => {
153
item . meta = Object . assign ( item . meta , { hidden : true })
154
155
156
157
})
}
return (
158
159
< Item {...{ key : menu . path }} >
< tag {...{ props , attrs }} >
160
161
162
163
164
165
{ this . renderIcon ( menu . meta . icon )}
< span > { menu . meta . title } < /span>
</ tag >
< /Item>
)
},
166
renderSubMenu ( menu ) {
167
168
169
170
171
const itemArr = []
if ( !menu.alwaysShow ) {
menu.children.forEach ( item => itemArr.push ( this.renderItem ( item )))
}
return (
172
<SubMenu {...{key: menu.path}}>
173
174
175
176
177
178
179
180
<span slot="title">
{this.renderIcon ( menu.meta.icon ) }
<span>{menu.meta.title}</ span >
< /span>
{itemArr}
</ SubMenu >
)
},
181
renderIcon ( icon ) {
182
183
184
185
186
187
if ( icon === 'none' || icon === undefined ) {
return null
}
const props = {}
typeof ( icon ) === 'object' ? props . component = icon : props . type = icon
return (
188
< Icon {...{ props }} />
189
190
191
192
)
}
},
193
194
render () {
const {mode, theme, menu} = this
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
const props = {
mode: mode,
theme: theme,
openKeys: this.openKeys
}
const on = {
select: obj => {
this.selectedKeys = obj.selectedKeys
this.$emit ( 'select', obj )
},
openChange: this.onOpenChange
}
const menuTree = menu.map ( item => {
if ( item.hidden ) {
return null
}
return this.renderItem ( item )
} )
/ / {...{ props , on : on }}
return (
216
< Menu vModel = { this . selectedKeys } {...{ props , on : on }} >
217
218
219
220
221
{ menuTree }
< /Menu>
)
}
}