在不使用ElementUi等框架的情况下,制作一个二级菜单,网上搜寻很多资料,但部分要不只显示HTML结构,不显示CSS样式,要不就是复杂的让人无法理解。

效果图:
Vue中二级菜单的实现

针对菜单做了CSS样式修饰,给一级二级菜单都添加了鼠标悬浮事件,当悬浮到某个菜单时,背景颜色,字体颜色发生改变。当点击某个一级菜单时,二级菜单实现显示和隐藏的动态切换。

菜单的HTML结构:
<div class="nav">
--------------------一级菜单------------------
<ul>
<li
v-for="item in menus"
:key="item.id"
@click="changeCheck(item.id)"
:class="{ check: currentTag == item.path }"
class="mainMenu"
>
<router-link
:to="{name:item.path,params:userName}"
class="mainA"
@click.native="TabName(item.title)"
>{{ item.title }}</router-link
>
------------------二级菜单----------------------
<ul v-if="item.children && item.active">
<li
class="subMneu"
v-for="(child, index) in item.children"
:key="index"
@click="clickSubMenu(item,child.title)"
>
<router-link
class="menuB"
:to="{name:child.path,params:userName}"
:class="{ menu_active: child.active }"
>{{ child.title }}</router-link
>
</li>
</ul>
</li>
</ul>
</div>
代码分析:
  1. 针对菜单采用的是ul列表,然后采用v-for循环对菜单数据进行循环,菜单采用的是动态样式 : class

当点击菜单的path地址和菜单中的某个path相等时,动态渲染该样式。

  1. li包含<router-link>是为了当点击该菜单时,跳转到相应的内容

菜单的JS代码:

data( )函数数据:

export default {
components: {
},
data() {
return {
menus: [
{ id: 1, title: "用户管理", path: "UserMannger", active: false },
{
id: 2,
title: "商品管理",
path: "goodsManger",
active: false,
children: [
{ id: 21, title: "增加商品", path: "addGoods", active: false },
],
},
{ di: 3, title: "关于我们", path: "about", active: false },
],
currentTag: "",
tabName: "",
flag2: true,
// tabName:'用户管理',
userName:''
};
},

JS代码

methods: {
changeCheck(id) {
const obj = this.menus.find((item) => item.id == id);
this.menus.find((item) => {
if (item.id == id) {
item.active = !item.active;
if (item.children) {
item.children.active = !item.active;
}
}
});
this.currentTag = obj.path;
},
clickSubMenu(main,val) {
this.tabName = val
main.children[0].active = !main.children[0].active
main.active = !main.children[0].active;
},
backHome() {
this.$router.push("/UserMannger/123");
},
getLogin2(val){
this.userName = val
},
TabName(val){
console.log(val);
this.tabName = val
}
},
created() {
this.$bus.$on('toHome',this.getLogin2)
},
};

方法中 changeCheck函数分析:

  1. 首先先接收点击菜单的id,对menus数字进行遍历,当id相同时,将该菜单的active属性进行动态改变,这样做是为了动态切换样式。在遍历中还要对子菜单进行判断,如果有子菜单则将该子菜单的active属性改变

方法中 clickSubMneu函数分析:

  1. 因为该方法是当点击子菜单触发此事件,触发事件时传入该子菜单的一级菜单,然后将该菜单的子菜单的active属性进行动态改变,并且将主菜单的active属性始终与子菜单保持相反。

  1. 因为这里只设置了一个子菜单所以下标为0,当需要设置多个子菜单时,还需要传入index和子菜单的index然后进行判断方法和对一级菜单的判断相同。

CSS代码
当点击子菜单的a标签的公共样式
.menu_active {
color: red;
display: block;
width: 100%;
text-decoration: none;
color: rgb(255, 208, 75);
background-color: #409eff;
}
菜单修饰
.nav {
height: 100%;
flex-grow: 1;
background-color: #001529;
ul {
.mainMenu {
margin-top: 20px;
width: 100%;
text-align: center;
line-height: 50px;
color: white;
.mainA {
display: block;
width: 100%;
text-decoration: none;
color: white;
&:hover {
background-color: #409eff;
}
&:active {
color: rgb(255, 208, 75);
}
}
}
}
}

这里采用的SCSS预编译语言:

在菜单css修饰中需要注意的是,一定要给一级菜单和二级菜单起名字,即使scss能够嵌套,依然会发生样式穿透的bug,所以针对一级菜单和二级菜单的样式进行单独修饰。

这里还需要知道的是 scss中有 :active和 : hover 的伪类用法,前者是当点击时触发该样式,后者是鼠标悬浮时触发的样式。