1 定義多級(jí)菜單
修改 src/router/index.js 的 / 路由
{
path: '/',
redirect: '/dashboard',
name: 'Container',
component: Container,
children: [
{path: 'dashboard', name: '首頁', component: Dashboard,
children: [
{path: 'dashboard1', name: '首頁1', component: Dashboard,},
{path: 'dashboard2', name: '首頁2', component: Dashboard,
children: [
{path: 'dashboard21', name: '首頁21', component: Dashboard,},
{path: 'dashboard22', name: '首頁22', component: Dashboard, },
] },
]
},
{path: 'article', name: '文章', component: Article, },
]
}
2 抽出Sidebar組件
生成的遞歸路由放在側(cè)邊欄,因此抽取 sidebar 組件绑洛,sidebar 包含logo和 遞歸路由
再抽取 SidebarItem 為單獨(dú)的路由組件,方便遞歸調(diào)用
2.1 Sidebar
Sidebar 接收collapse萍虽、路由數(shù)組膜蠢,同時(shí)引入 SidebarItem 組件
子組件傳入:
- barIdx: 當(dāng)前路由的索引,用來定位子菜單
- subroute: 路由對(duì)象
- fatherpath: 父路徑滋恬,如 /、 /a/b
<template>
<div>
<div class="app-side-logo">
<img src="@/assets/logo.png"
:width="collapse ? '60' : '60'"
height="60" />
</div>
<el-menu class="el-menu-vertical-demo"
:default-active="defaultActive"
router
:collapse="collapse"
>
<SidebarItem v-for="(item, idx) in routes"
:subroute="item"
:fatherpath="fatherPath"
:barIdx="idx" :key="idx" />
</el-menu>
</div>
</template>
<script>
import SidebarItem from './SidebarItem'
export default {
naem: "Sidebar",
components: {
SidebarItem
},
props: {
collapse: {
type: Boolean
},
routes: {
type: Array
}
},
computed: {
// 首次進(jìn)入頁面時(shí)展開當(dāng)前頁面所屬的菜單
defaultActive(){
return this.$route.path
},
fatherPath(){
// 這里直接獲取路由配置的 '/' 項(xiàng)
return this.$router.options.routes[1].path
}
}
}
</script>
<style>
</style>
2.2 SidebarItem
SidebarItem 接收路由抱究、父路由path恢氯、父級(jí)idx,然后遞歸調(diào)用自身
<template>
<!-- 如果當(dāng)前 subroute 有子節(jié)點(diǎn) -->
<el-submenu v-if="!subroute.hidden && subroute.children && subroute.children.length > 0"
:index="genPath(fatherpath, subroute.path)">
<!-- 創(chuàng)建菜單分組 -->
<template slot="title">
<i class="el-icon-menu"></i>
<span slot="title">{{subroute.name}}</span>
</template>
<!-- 遞歸調(diào)用自身鼓寺,直到 subroute 不含子節(jié)點(diǎn) -->
<SidebarItem v-for="(submenu, subidx) in subroute.children"
:subroute="submenu"
:fatherpath="genPath(fatherpath, subroute.path)"
:barIdx="subidx"
:key="barIdx + '-' + subidx"
/>
</el-submenu>
<!-- 當(dāng)前節(jié)點(diǎn)不含子節(jié)點(diǎn)且非隱藏 -->
<el-menu-item style="font-weight: 400"
v-else-if="!subroute.hidden"
:index="genPath(fatherpath, subroute.path)"
>{{subroute.name}}
</el-menu-item>
<el-menu-item style="font-weight: 400"
v-else
:index="genPath(fatherpath, subroute.path)"
>{{ subroute.name }}
</el-menu-item>
</template>
<script>
export default {
name: 'SidebarItem',
props: {
subroute: {
type: Object
},
barIdx: {
type: [String, Number]
},
fatherpath: {
type: String
}
},
computed: {
// 默認(rèn)激活的路由, 用來激活菜單選中狀態(tài)
defaultActive: function(){
return this.$route.path
},
},
methods: {
// 生成側(cè)邊欄路由勋拟,格式: /a/b/c
genPath: function(){
let arr = [ ...arguments ]
let path = arr.map(v => {
while (v[0] === '/'){
v = v.substring(1)
}
while(v[-1] === '/'){
v = v.substring(0, v.length)
}
return v
}).join('/')
path = path[0] === '/' ? path : '/'+path
return path
},
handleOpen: function(key, keyPath) {
console.log(key, keyPath)
},
handleClose: function(key, keyPath) {
console.log(key, keyPath)
}
},
mounted: function(){
console.log('sidebar routes: ', this.routes)
}
}
</script>
<style>
</style>
3 項(xiàng)目結(jié)構(gòu)
此時(shí) src 的目錄結(jié)構(gòu)
│ App.vue
│ main.js
├─assets
│ logo.png
├─components
│ HelloWorld.vue
│ Sidebar.vue
│ SidebarItem.vue
├─container
│ Container.vue
├─router
│ index.js
├─styles
│ index.scss
└─views
│ TheLogin.vue
├─article
│ index.vue
└─dashboard
index.vue
4 修改容器配置
src/container/Container.vue 引入 Sidebar 組件
<template>
<!-- ... -->
<el-aside class="app-side app-side-left"
:class="isCollapse ? 'app-side-collapsed' : 'app-side-expanded'">
<Sidebar :collapse="isCollapse" :routes="$router.options.routes[1].children"/>
</el-aside>
<!-- ... -->
</template>
<script>
import Sidebar from '@/components/Sidebar'
export default {
name: 'Container',
components: {
Sidebar
},
/** ... */
</script>
頁面效果
image
image