版本
ant-design-vue
:"^1.7.4"
,
常用属性
属性 | 说明 | 默认值 |
---|---|---|
mode | 菜单类型,现在支持垂直、水平、和内嵌模式三种 | vertical |
inlineCollapsed | inline 时菜单是否收起状态 | |
theme | 主题颜色(light /dark ) | light |
openKeys(.sync) | 当前展开的 SubMenu 菜单项 key 数组 | |
defaultOpenKeys | 初始展开的 SubMenu 菜单项 key 数组 | |
selectedKeys(v-model) | 当前选中的菜单项 key 数组 | |
defaultSelectedKeys | 初始选中的菜单项 key 数组 |
说明
defaultSelectedKeys
是默认选中的key
(a-menu-item
上绑定的key
),被选中会有高亮的显示效果;selectedKeys
也是一样的作用,不要同时使用,区别在于如果只希望指定一个初始化的菜单选项就使用defaultSelectedKeys
,如果需要通过自己修改数据来选中菜单的选中项就使用selectedKeys
。
(openKeys
和defaultOpenKeys
也是同理)
常用事件
openChange
是Menu
的事件,SubMenu
展开/关闭的回调
递归嵌套多级菜单
若只有两级菜单则直接使用v-for
和v-if
指令即可完成;若菜单级数≥3则需要使用函数式组件
。具体原因官网已经做了说明:
Before v2.0, 因组件内部会动态更改
a-sub-menu
的属性,如果拆分成单文件,无法将属性挂载到a-sub-menu
上,你需要自行声明属性并挂载。为了方便,避免属性的声明,我们推荐使用函数式组件。
代码
App.vue
(测试就随便在App.vue
里写了)
<template>
<div id="app">
<div style="width: 256px">
<a-button type="primary" style="margin-bottom: 16px" @click="toggleCollapsed">
<a-icon :type="collapsed ? 'menu-unfold' : 'menu-fold'" />
</a-button>
<a-menu
:defaultSelectedKeys="[$route.path]"
:openKeys="openKeys"
mode="inline"
theme="dark"
:inline-collapsed="collapsed"
@openChange="onOpenChange"
@click="menuClick"
>
<template v-for="item in list">
<a-menu-item v-if="!item.children" :key="item.path">
<a-icon type="pie-chart" />
<span>{{ item.title }}</span>
</a-menu-item>
<sub-menu v-else :key="item.path" :menu-info="item" />
</template>
</a-menu>
</div>
<router-view/>
</div>
</template>
<script>
import { Menu } from 'ant-design-vue';
const SubMenu = {
template: `
<a-sub-menu :key="menuInfo.key" v-bind="$props" v-on="$listeners">
<span slot="title">
<a-icon type="mail" /><span>{{ menuInfo.title }}</span>
</span>
<template v-for="item in menuInfo.children">
<a-menu-item v-if="!item.children" :key="item.path">
<a-icon type="pie-chart" />
<span>{{ item.title }}</span>
</a-menu-item>
<sub-menu v-else :key="item.path" :menu-info="item" />
</template>
</a-sub-menu>
`,
name: 'SubMenu',
// must add isSubMenu: true 此项必须被定义
isSubMenu: true,
props: {
// 解构a-sub-menu的属性,也就是文章开头提到的为什么使用函数式组件
...Menu.SubMenu.props,
// Cannot overlap with properties within Menu.SubMenu.props
menuInfo: {
type: Object,
default: () => ({}),
},
},
};
export default {
name: "App",
components: {
'sub-menu': SubMenu,
},
data() {
return {
collapsed: false,
openKeys: [],
rootSubmenuKeys: ['/user'],
list: [
{
key: '1',
title: '信息管理',
path: '/info',
},
{
key: '2',
title: '用户管理',
path: '/user',
children: [
{
key: '2.1',
title: '后台用户',
path: '/adminUser',
children: [
{
key: '2.1.1',
title: '新增用户',
path: '/addAdminUser',
children: [
{
key: '2.1.1。1',
title: '用户xx',
path: '/addAdminUserXX',
}
]
}
]
},
{
key: '2.2',
title: '前台用户',
path: '/frontUser',
}
]
}
],
};
},
created(){
const openKeys = window.sessionStorage.getItem('openKeys')
if(openKeys){
this.openKeys = JSON.parse(openKeys)
}
},
methods: {
toggleCollapsed() {
this.collapsed = !this.collapsed;
},
onOpenChange(openKeys) {
// 将当前打开的父级菜单存入缓存中
window.sessionStorage.setItem('openKeys', JSON.stringify(openKeys))
// 控制只打开一个
const latestOpenKey = openKeys.find(key => this.openKeys.indexOf(key) === -1);
if (this.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
this.openKeys = openKeys;
} else {
this.openKeys = latestOpenKey ? [latestOpenKey] : [];
}
},
menuClick({key}) {
// 获取到当前的key,并且跳转
this.$router.push({
path: key
})
},
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
padding: 50px;
}
</style>
这里省略了router
配置,相信在座的各位也会!(不会的底下留言,包教包会!)
如果
vue
报编译错误You are using the runtime-only build of Vue
,可以在vue的配置文件里加一行runtimeCompiler: true
,重新运行即可。
如果点击同一个菜单报错了NavigationDuplicated: Avoided redundant navigation to current location
,需要修改下Router
设置(router/index.js
):
const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
效果
自动渲染多级嵌套菜单;刷新会保存选中的菜单;点击菜单,收起其他展开的所有菜单。