用ANTD-Vue做管理页面的左侧菜单 需要在刷新后也能保持左侧菜单被选中和展开 且只能展开一个菜单
这个比较简单
ANTD的API中提供了一个defaultSelectedKeys参数
描述:初始选中的菜单项 key 数组
类型: string[] 自己手动实验得知意思就是在数组中填入字符串 例如[‘key’]
默认值为空
一级菜单和子菜单都有一个key属性,我后端返回的json数据中的router属性是每个菜单的路由跳转地址 也赋值给了菜单的key 这样点击菜单跳转后 用this.$route.path获取到的当前路由地址就和菜单的key一致了
在菜单标签中设置 defaultSelectedKeys属性指向this.$route.path即可完成
可展开(有二级菜单)的一级菜单点击后会展开或收起 不会发生跳转
ANTD提供了两个api:
openKeys 当前展开的 SubMenu 菜单项 key 数组
defaultOpenKeys 初始展开的 SubMenu 菜单项 key 数组
两个api中的描述 一个是"当前" 另一个是"初始(默认)" ,试了半天后发现用defaultOpenKeys设置值后是只生效一次的 也就是说等如果设置defaultOpenKeys的对应属性为空 等ajax请求到数据后再去设置,菜单就不会变化了,所以不能用这个
openKeys
看来只能用openKeys了,我又发现一个小问题,设置openKeys后手动点击其他没展开的菜单,菜单不会有变化 这样就得用到另一个API
openChange 展开/关闭的回调
每次点击可展开/收起的菜单时都会触发这个属性所对应的函数,设置openKeys后再配合openChange切换菜单即可解决问题
具体请看代码
VUE html代码部分(只截取了菜单部分)
<template v-for="item in menuList"> // 渲染菜单列表
<a-menu-item v-if="item.children === false" :key="item.router"> // 顶级菜单
<span>{{ item.name }}span>
a-menu-item>
<a-sub-menu v-else :key="item.router"> // 可以展开的二级菜单
<span slot="title"><span>{{ item.name }}span>span>
<a-menu-item v-for="menuChildren in item.children" :key="menuChildren.router">{{ menuChildren.name }}a-menu-item>
a-sub-menu>
template>
a-menu>
后端返回的JSON数据格式:
[
{
"name": "首页",
"router": "/home/index",
"children": false
},
{
"name": "商品管理",
"router": "/shop", // 点击这个菜单不会跳转 只会展开 此处的router是为了设置key属性
"children": [
{
"name": "商品分类",
"router": "/home/shopClass"
},
{
"name": "商品列表",
"router": "/home/shopList"
}
]
},
{
"name": "个人设置",
"router": "/user",
"children": [
{
"name": "我的资料",
"router": "/home/userEdit"
},
{
"name": "登录记录",
"router": "/home/userLoginRecord"
}
]
}
]
export default {
data() {
return {
defaultSelectedKeys: [this.$route.path],
openKeys: [''],
menuList: [] // 此处为动态获取的菜单数组
}
},
async created() {
const result = await this.$http.post('home/menuList') // post后端服务器获取菜单数据
this.menuList = result // 给data里面的菜单数组赋值数据
this.xhmenu(result) // 处理数据 请原谅这让人看不懂的命名 o(╥﹏╥)o
},
methods: {
xhmenu(result) {
for (let i = 0; i < this.menuList.length; i++) {
//循环【顶级菜单数组列表】 循环的数组下标用i表示
if (result[i].children !== false) {
// 如果这个菜单没有【子菜单】 就不继续了(没有子菜单就是【点击可跳转页面但不会展开】的顶级菜单)
for (let y = 0; y < result[i].children.length; y++) {
// 循环【顶级菜单】的子菜单数组(二级菜单)数组下标用y表示
if (result[i].children[y].router === this.$route.path) {
// 如果子菜单的router数据和当前路由地址一样 则断定现在的页面就停留在这个数组对应的菜单中
this.openKeys = [result[i].router]
// 那么就把【顶级菜单(循环数组下标为i)的router属性】赋值给this.openKeys【data中当前展开的菜单】
}
}
}
}
},
onOpenChange(openKeys) { // 当菜单被展开时触发此处
/*
经测试传入的变量openKeys是数组 点击已经展开的菜单时传入的是空数组
点击未展开的菜单时传入的是[当前展开菜单的key,点击的菜单key]
下面的if判断用openKeys === [] 无效 所以我只能判断数组length是否等于0
*/
if (openKeys.length !== 0) {
this.openKeys = [openKeys[1]]
} else {
this.openKeys = ['']
}
},
clickItem(obj) {
this.$router.push(obj.key)
}
}
}