Vue 与 elementui 实现递归组件菜单
主要讲如何使用 vue 实现一个递归组件,一般这种组件,多用于项目中的导航菜单。递归的主要思想就是自己调用自己,然后有结束条件。递归组件也是一样,在组建内使用自己(需要注意的是一个 name 属性,这个属性相当于组件的标识,自己调用自己就用的这个,其实 keep-alive 用到的 exclude 等也是这个属性而不是路由里面的 name。),下面是我写的一个递归的导航菜单,毕竟看代码实例来的更清晰点。
主菜单
<template>
<div class="lj-left-menu">
<el-menu
:default-active="activeIndex"
class="el-menu-vertical-demo"
background-color="#242F4B"
text-color="#D2D5DE"
active-text-color="#468FFE"
ref="activeIndex"
>
<menu-item :menuData="menuData"></menu-item>
</el-menu>
</div>
</template>
<script>
import menuItem from "./menuItem";
export default {
name: "leftMenu",
components: {
menuItem,
},
data() {
return {
activeIndex: null, // 当前展开菜单
menuData: [
{
id: "0",
title: "首页",
router: "/home",
icon: "el-icon-s-home",
children: [],
},
{
id: "1",
title: "巡检",
icon: "el-icon-place",
router: "/home",
children: [
{
id: "1-0",
title: "智能巡检设置",
icon: "",
router: "/home",
children: [],
},
{
id: "1-1",
title: "巡检记录",
icon: "",
router: "/home",
children: [],
},
{
id: "1-2",
title: "人工巡检任务",
icon: "",
router: "/home",
children: [],
},
{
id: "1-3",
title: "故障维修",
icon: "",
router: "/home",
children: [],
},
{
id: "1-4",
title: "保养维护任务",
icon: "",
router: "/home",
children: [],
},
],
},
{
id: "2",
title: "设备管理",
icon: "el-icon-s-management",
router: "",
children: [
{
id: "2-0",
title: "设备管理",
icon: "",
router: "/home",
children: [],
},
{
id: "2-1",
title: "设备生命周期管理",
icon: "",
router: "/home",
children: [],
},
],
},
{
id: "3",
title: "告警管理",
icon: "el-icon-sunrise",
router: "/home",
children: [
{
id: "3-0",
title: "巡检告警",
icon: "",
router: "/home",
children: [],
},
],
},
{
id: "4",
title: "消息中心",
icon: "el-icon-chat-dot-square",
router: "/home",
children: [
{
id: "4-0",
title: "消息列表",
icon: "",
router: "/home",
children: [],
},
],
},
{
id: "5",
title: "系统管理",
icon: "el-icon-setting",
router: "/home",
children: [
{
id: "5-0",
title: "用户管理",
icon: "",
router: "/home",
children: [
{
id: "5-0-1",
title: "权限管理",
icon: "",
router: "/home",
children: [],
},
],
},
{
id: "5-1",
title: "角色管理",
icon: "",
router: "/home",
children: [],
},
{
id: "5-2",
title: "权限管理",
icon: "",
router: "/home",
children: [],
},
],
},
],
};
},
computed: {},
mounted() {},
methods: {},
watch: {
$route: { // 监听路由,确保刷新后当前页面与导航状态一致。
handler(val) {
this.activeIndex = val.meta.id;
},
deep: true,
immediate: true,
},
},
};
</script>
<style lang='scss' scoped>
.lj-left-menu {
width: 100%;
height: 100%;
overflow: auto;
}
</style>
递归组件
<template>
<div class="lj-menu-item">
<template v-for="item in menuData">
<template v-if="item.children.length">
<el-submenu :index="item.id" :key="item.id">
<template slot="title">
<template v-if="item.icon">
<i :class="item.icon"></i>
<span></span>
</template>
<template v-else>
<div class="radius"></div>
<div></div>
</template>
</template>
<menu-item :menuData="item.children"></menu-item>
</el-submenu>
</template>
<template v-else>
<el-menu-item
:index="item.id"
:key="item.id"
@click="goRouter(item.router)"
>
<template v-if="item.icon">
<i :class="item.icon"></i>
<span></span>
</template>
<template v-else>
<div class="radius"></div>
<div></div>
</template>
</el-menu-item>
</template>
</template>
</div>
</template>
<script>
export default {
name: "menuItem",
data() {
return {
nowRouter: null,
};
},
props: {
menuData: {
type: Array,
default: () => {},
},
},
computed: {},
mounted() {
this.nowRouter = this.$route.path;
},
methods: {
// 路由跳转
goRouter(data) {
if (this.nowRouter === data) {
return;
} else {
this.nowRouter = data;
this.$router.push(data);
}
},
},
};
</script>
<style lang="scss">
.el-menu-item.is-active {
background: linear-gradient(90deg, #2b579c 0%, rgba(52, 89, 150, 0) 100%);
border-left: 2px solid #0086ff;
}
.el-menu-item:focus,
.el-menu-item:hover {
background: linear-gradient(90deg, #2b579c 0%, rgba(52, 89, 150, 0) 100%);
border-left: 2px solid #0086ff;
}
.el-submenu__title {
i {
color: #00d7ff !important;
}
}
.el-menu-item,
.el-submenu__title {
display: flex;
justify-content: flex-start;
align-items: center;
.radius {
width: 8px;
height: 8px;
background: #468ffe;
opacity: 0.6;
border-radius: 50%;
margin-right: 10px;
}
i {
color: #00d7ff !important;
}
}
</style>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Vue 路由实现原理
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论