由于近来公司业务繁忙,以至于没时间去接着做antd的项目。emmm…后面应该还会忙些时间!
antd的路由导航还是有些坑的,对习惯了element的小伙伴来说不那么理想。这里先记录一下如何通过路由来动态生成1~2级导航菜单了(之后会出三级及以上导航菜单爬坑日志)。注: 此文为过渡文,没怎么上心,表达不明之处还请见谅,另外,欢迎打扰~~~~项目在线地址 (有用的话,记得给个start哦)
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
name: 'Home',
component: () => import('@/views/dashboard/index'),
meta: {
title: 'Dashboard', icon: 'user' }
}
]
}
<a-menu theme="dark" mode="inline" :selected-keys="currentSelectMenu" :open-keys="openKeys" @click="menuClick" @openChange="onOpenChange">
<template v-for="item in routers">
<template v-if="!item.hidden && item.children">
<a-menu-item v-if="item.children.length === 1" :key="item.path === '/' ? `${item.path}${item.children[0].path}`: `${item.path}/${item.children[0].path}`">
<a-icon :type="item.children[0] && item.children[0].meta && item.children[0].meta.icon" />
<router-link style="display: inline-block" :to="{path: item.path === '/' ? `${item.path}${item.children[0].path}` : `${item.path}/${item.children[0].path}`}">
{
{ generateTitle(item.children[0].meta.title) }}
router-link>
a-menu-item>
<a-sub-menu v-else :key="item.path">
<span slot="title">
<a-icon :type="item.meta && item.meta.icon" />
<span v-if="item.meta">{
{ generateTitle(item.meta.title) }}span>
span>
<template v-for="subItem in item.children">
<a-menu-item v-if="!subItem.children" :key="item.path + '/' + subItem.path">
<a-icon v-if="subItem.meta.icon" :type="subItem.meta && subItem.meta.icon" />
<router-link style="display: inline-block" :to="item.path + '/' + subItem.path">
{
{ generateTitle(subItem.meta.title) }}
router-link>
a-menu-item>
template>
a-sub-menu>
template>
template>
a-menu>
这里涉及到的a-menu属性啥的就不详细赘述了,官方文档挺好的(主要是表达能力着实不行…),这里说一下所用到的属性及事件吧。
// 当前选中的菜单项(这里直接返回path即可)
currentSelectMenu() {
return [this.$route.path]
}
open-keys:当前展开的 SubMenu 菜单项 key 数组,这里的key数组必须与父节点菜单的key值相对应。实现openKeys与父节点菜单的key的方法有很多,最初采用的是将其存入浏览器的sessionStorage(有些麻烦,后期在做三级菜单的时候移除了)。openChange:SubMenu 展开/关闭的回调,主要是为了控制当前submenu菜单是否展开/关闭;
// 通过菜单栏的点击事件menuClick将当前菜单的key存入sessionStorage
menuClick({
item, key, keyPath }) {
// length为1则说明没有子菜单
if (keyPath.length === 1) {
this.openKeys = []
window.sessionStorage.clear()
} else window.sessionStorage.setItem('open-menu-key', keyPath.pop()) // 将副路由存入sessionStorage,展开激活submenu菜单
},
// 在created生命周期获取,初始化展开submenu
const openKeys = window.sessionStorage.getItem('open-menu-key')
if (openKeys) this.openKeys = [openKeys]
// openChange:SubMenu 展开/关闭的回调,主要是为了控制当前submenu菜单是否展开/关闭
// 子菜单展开/关闭的回调
onOpenChange(openKeys) {
const latestOpenKey = openKeys.find(key => this.openKeys.indexOf(key) === -1)
this.openKeys = this.rootSubmenuKeys.indexOf(latestOpenKey) === -1 ? openKeys : latestOpenKey ? [latestOpenKey] : []
}
最后,附上全部代码
<template>
<div class="sidebar-container">
<a-layout-sider v-model="isCollapsed" :trigger="null" collapsible>
<div class="logo" />
<a-menu theme="dark" mode="inline" :selected-keys="currentSelectMenu" :open-keys="openKeys" @click="menuClick" @openChange="onOpenChange">
<template v-for="item in routers">
<template v-if="!item.hidden && item.children">
<a-menu-item v-if="item.children.length === 1" :key="item.path === '/' ? `${item.path}${item.children[0].path}`: `${item.path}/${item.children[0].path}`">
<a-icon :type="item.children[0] && item.children[0].meta && item.children[0].meta.icon" />
<router-link style="display: inline-block" :to="{path: item.path === '/' ? `${item.path}${item.children[0].path}` : `${item.path}/${item.children[0].path}`}">
{
{ generateTitle(item.children[0].meta.title) }}
router-link>
a-menu-item>
<a-sub-menu v-else :key="item.path">
<span slot="title">
<a-icon :type="item.meta && item.meta.icon" />
<span v-if="item.meta">{
{ generateTitle(item.meta.title) }}span>
span>
<template v-for="subItem in item.children">
<a-menu-item v-if="!subItem.children" :key="item.path + '/' + subItem.path">
<a-icon v-if="subItem.meta.icon" :type="subItem.meta && subItem.meta.icon" />
<router-link style="display: inline-block" :to="item.path + '/' + subItem.path">
{
{ generateTitle(subItem.meta.title) }}
router-link>
a-menu-item>
template>
a-sub-menu>
template>
template>
a-menu>
a-layout-sider>
div>
template>
<script>
// 国际化导航菜单title
import {
generateTitle } from './breadcrumb/index.js'
export default {
name: 'SubMenu',
props: {
collapsed: [Boolean],
routers: {
type: Array,
default: () => []
}
},
data() {
return {
isCollapsed: false,
onlyOneChild: null,
openKeys: [''],
rootSubmenuKeys: ['/form', '/about'] // submenu数组
}
},
computed: {
// 当前选中的菜单项
currentSelectMenu() {
return [this.$route.path]
},
router() {
return this.$route.path
}
},
watch: {
collapsed: {
handler: function(val) {
this.isCollapsed = val
}
}
},
created() {
// 获取当前副路由(需要展开)
const openKeys = window.sessionStorage.getItem('open-menu-key')
if (openKeys) this.openKeys = [openKeys]
},
methods: {
generateTitle,
// 点击菜单触发事件
menuClick({
item, key, keyPath }) {
// length为1则说明没有子菜单
if (keyPath.length === 1) {
this.openKeys = []
window.sessionStorage.clear()
} else window.sessionStorage.setItem('open-menu-key', keyPath.pop()) // 将副路由存入sessionStorage,展开激活submenu菜单
},
// 子菜单展开/关闭的回调
onOpenChange(openKeys) {
const latestOpenKey = openKeys.find(key => this.openKeys.indexOf(key) === -1)
this.openKeys = this.rootSubmenuKeys.indexOf(latestOpenKey) === -1 ? openKeys : latestOpenKey ? [latestOpenKey] : []
}
}
}
script>
<style lang="less" scoped>
.logo {
height: 32px;
background: rgba(255, 255, 255, 0.2);
margin: 16px;
}
style>