Vue动态菜单,面包屑
# Vue动态菜单,面包屑
# vue动态路由渲染菜单
实现效果:
准备数据:mock/index.json
"menuType": "1", 菜单
"menuType": "2", 按钮
[
{
"_id": "600d4075e218daaf4ec77e52",
"menuType": "1",
"menuName": "系统管理",
"path": "/system",
"icon": "el-icon-setting",
"children": [
{
"_id": "600d525e602f452aaeeffcd9",
"menuType": "1",
"menuName": "用户管理",
"path": "/system/user",
"children": [
{
"_id": "6030ca8f93f0e159c8390f0c",
"menuType": "2",
"menuName": "新增",
"menuCode": "user-create"
},
{
"_id": "603226d9257d15a8c54cf9f8",
"menuType": "2",
"menuName": "批量删除",
"menuCode": "user-delete"
},
{
"_id": "603253e0a821c6bb59084541",
"menuType": "2",
"menuName": "查看",
"menuCode": "user-query"
}
]
},
{
"_id": "601bc4f8a794e23c2e42efa9",
"menuType": "1",
"menuName": "菜单管理",
"path": "/system/menu",
"children": [
{
"_id": "60325400a821c6bb59084543",
"menuType": "2",
"menuName": "查看",
"menuCode": "menu-query"
},
{
"_id": "6032540fa821c6bb59084544",
"menuType": "2",
"menuName": "创建",
"menuCode": "menu-create"
}
]
}
]
},
{
"_id": "601b9eb25929c81a1f988bb0",
"menuType": "1",
"menuName": "审批管理",
"path": "/audit",
"icon": "el-icon-s-promotion",
"children": [
{
"_id": "601bc763a794e23c2e42efaa",
"menuType": "1",
"menuName": "休假申请",
"path": "/audit/leave",
"children": [
{
"_id": "603254a8a821c6bb59084549",
"menuType": "2",
"menuName": "查看",
"menuCode": "leave-query"
},
{
"_id": "603254baa821c6bb5908454a",
"menuType": "2",
"menuName": "申请休假",
"menuCode": "leave-create"
}
]
}
]
}
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
Home.vue
<template>
<div class="home">
<el-container style="height: 100%; border: 1px solid #eee">
<!--侧边栏-->
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<!--菜单导航-->
<el-menu router>
<TreeMenu :menuData="menuData"></TreeMenu>
</el-menu>
</el-aside>
<!--主题区域-->
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</div>
</template>
<script>
import menuData from '../../mock/index.json'
import TreeMenu from "@/components/TreeMenu";
export default {
name: 'Home',
components: {TreeMenu},
data() {
return {
menuData
}
}
}
</script>
<style lang="scss" scoped>
.home {
height: 100vh;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
TreeMenu.vue
<!--
思路 :
1. 获取传递进来的数据
2. 使用 el-sub-menu 进行一个遍历 , 遍历传递过来的所有数据, 并且判断他是否有 children , 如果有children ,并且 menuType 为 1 的情况
则使用 munuName 生成一个组
3. 递归判断是否有多级 children , 如果有 则继续生成下一级菜单
4. 判断到最后一个层级 , 如果说 menuType === 1 情况下,name这个肯定是可以 按钮 ,而不是一个组 所以, 这个应该用 el-menu-item 进行渲染
-->
<template>
<div>
<template v-for="item in menuData">
<!--一级菜单渲染-->
<el-submenu
:index="item._id"
v-if="item.children && item.children.length > 0 && item.children[0].menuType.toString() === '1'"
>
<template slot="title">
<i :class="item.icon"></i>
<span>{{ item.menuName }}</span>
</template>
<!--递归自己-->
<TreeMenu :menuData="item.children"></TreeMenu>
</el-submenu>
<!--多级菜单-->
<!--没有孩子,并且不是按钮,就渲染上-->
<el-menu-item
v-else-if="item.menuType.toString() === '1'"
:index="item.path"
:key="item._id"
>
{{item.menuName}}
</el-menu-item>
</template>
</div>
</template>
<script>
export default {
name: 'TreeMenu',
props: {
menuData: {
type: Array,
required: true
}
},
}
</script>
<style lang="scss" scoped>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Vue动态面包屑
先来了解一下$route里面存储的信息,可以发现matched里面存储了当前路径的路由信息
router->index.js
利用路由元信息标记当前路径的菜单标题
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../components/Home'),
meta: {
title: "首页"
},
children: [
{
path: '/system',
name: 'system',
component: () => import('../views/System.vue'),
meta: {
title: "系统管理"
},
children: [
{
path: 'user',
name: 'user',
component: () => import('../views/User.vue'),
meta: {
title: "用户管理"
},
},
{
path: 'menu',
name: 'menu',
component: () => import('../views/Menu.vue'),
meta: {
title: "菜单管理"
},
},
]
},
{
path: '/audit',
name: 'audit',
component: () => import('../views/Audit.vue'),
meta: {
title: "审批管理"
},
children: [
{
path: 'leave',
name: 'leave',
component: () => import('../views/Leave.vue'),
meta: {
title: "休假管理"
},
}
]
}
]
},
]
// 动态,添加的路由
export const dynamicRouters = [
{
path: '/test',
name: 'test',
component: () => import('../views/Test.vue'),
},
{
path: '/permission',
name: 'permission',
component: () => import('../views/Permission'),
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
// // 循环遍历路由添加上去
// dynamicRouters.forEach( (item) => {
// router.addRoute(item)
// })
export default router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
Home.vue
<template>
<div class="home">
<el-container style="height: 100%; border: 1px solid #eee">
<!--侧边栏-->
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<!--菜单导航-->
<el-menu router>
<TreeMenu :menuData="menuData"></TreeMenu>
</el-menu>
</el-aside>
<!--主题区域-->
<el-main>
<!--面包屑-->
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: breadCrumbItem.path }" v-for="breadCrumbItem in BreadcrumbList" :key="breadCrumbItem.path">
{{breadCrumbItem.meta.title}}
</el-breadcrumb-item>
</el-breadcrumb>
<router-view></router-view>
</el-main>
</el-container>
</div>
</template>
<script>
import menuData from '../../mock/index.json'
import TreeMenu from "@/components/TreeMenu";
export default {
name: 'Home',
components: {TreeMenu},
data() {
return {
menuData
}
},
computed: {
BreadcrumbList() {
return this.$route.matched
}
},
mounted() {
console.log(this.$route)
}
}
</script>
<style lang="scss" scoped>
.home {
height: 100vh;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
实现效果
编辑 (opens new window)
上次更新: 2024/12/19, 09:15:30