首先,我们先看下阿里云的导航菜单的样式,对这个样式有一个了解。
这个菜单,类似于那种树形菜单,用v-for循环就行了这样的菜单,可以看下这个Vue + ElementUI 手撸后台管理网站基本框架(三)登录及系统菜单加载
###首先,我们的数据模式要可配的,使用json数据格式,用递归实现
menuList: [
{
label: "菜单一",
children: [
{
label: "二级菜单_1",
children: [
{
label: "三级菜单_1",
children: [
{
label: "四级菜单_1"
}
]
}
]
},
{
label: "二级菜单_2",
}
]
},
{
label: "菜单二",
children: [
{
label: "二级菜单",
children: [
{
label: "三级菜单_1"
}
]
}
]
}
],
我们先看一下,我们生成的html代码的样式
<div class="cascader">
<div class="cascader-panel">
<ul>
<li class="cascader-item">
<p>菜单一</p>
</li>
<li class="cascader-item">
<p>菜单二</p>
</li>
</ul>
<div class="cascader-panel">
<ul>
<li class="cascader-item">
<p>二级菜单_1</p>
</li>
<li class="cascader-item">
<p>二级菜单_2</p>
</li>
</ul>
<div class="cascader-panel">
...
</div>
</div>
</div>
</div>
其实就是cascader-panel里套着cascader-panel,自己套自己,就能用递归来实现.
cascaderpanel.vue文件
<template>
<div class="cascader-panel" >
<ul v-if="data && data.length">
<li :class="[{isactive:currentIndex===index}]" v-for="(item,index) in data" :data="item" :key="item.id" @mouseenter="showChild(item,index)" ><p>{{item.label}}</p></li>
</ul>
<cascader-panel v-if="childMenu && childMenu.length" :data="childMenu"></cascader-panel>
</div>
</template>
<script>
export default {
name: "CascaderPanel",
props: {
data: Array
},
data() {
return {
childMenu: [],
currentIndex:-1,
};
},
watch: {
data() {
this.childMenu= [];
}
},
methods: {
showChild(item,index) {
this.currentIndex=index;
this.childMenu = item.children;
},
}
};
</script>
<style scoped>
.cascader-panel {
display: flex;
height: 100%;
}
.isactive{
color: blue;
}
li{
width: 120px;
cursor: pointer;
}</style>
调用的时候,我是在app.vue中调用的.
代码如下:
<template>
<div id="app">
<div @mouseenter="showall()" @mouseleave="showaleave()">
<button >主菜单</button>
<div class="cascader" v-show="show">
<cascader-panel :data="menuList"></cascader-panel>
</div>
</div>
<p>111111111111111111111111111111111111111111111111111111111111111111111111</p>
</div>
</template>
<script>
import CascaderPanel from "./components/CascaderPanel";
export default {
components: {
CascaderPanel
},
props: {
data: Array,
},
data() {
return {
menuList: [
{
label: "菜单一",
children: [
{
label: "二级菜单_1",
children: [
{
label: "三级菜单_1",
children: [
{
label: "四级菜单_1"
}
]
}
]
},
{
label: "二级菜单_2",
}
]
},
{
label: "菜单二",
children: [
{
label: "二级菜单",
children: [
{
label: "三级菜单_1"
}
]
}
]
}
],
show:false,
}
},
methods:{
showall(){
this.show=true;
},
showaleave(){
this.show=false;
},
}
};
</script>
<style>
.cascader{
position: absolute;
height: 100%;
background-color: #eee;
}
</style>
此时的效果
现在有四个问题(仔细观察图片,或者自己运行代码)
1.鼠标离开按钮"主菜单"时,级联菜单的不隐藏,要离开很远,才隐藏(这是因为我们把button和级联菜单放在了一个div里,而mouseenter事件绑定在了这个div上,只有离开这个div,级联菜单才能隐藏.)
所以我们把button和div添加一样的width和height,这样就好了
.btn,.div{
height: 50px;
width: 100px;
}
2.当我们第二次进入按钮上时,它打开的是你上次最后离开是的样子,
找一个临时变量,来存取数据,当鼠标进入btn时,数据存入,离开,数据清空.
<cascader-panel :data="list"></cascader-panel>
showall(){
this.show=true;
this.list=this.menuList;
},
showaleave(){
this.show=false;
this.list=[];
},
3.跟上一个问题相似,当你进入菜单一下面的菜单时,在进入其他菜单,再回来是,菜单一下面的还是有hover样式.
这个样式是这样添加的
我们把这个currentIndex 赋值了,但是并没有清空,所以我们监听这个值,只要它变化,就变成默认-1(-1是不存在)就好了.
watch: {
data() {
this.childMenu= [];
this.currentIndex= -1;
}
},
4 this.childMenu的清空也是这个原理.(如果不清空,就一直存在)
这个问题,我在li下面加一个空白标签,给他添加一个mouseenter的方法(如果有更好的方法,可以提供给我)
<div @mouseenter="enterul()" style="height:100%;"></div>
enterul(){
this.currentIndex = -1;
this.childMenu = [];
}
目前就是这些,这个代码拆的不是很大,就是一个组件,一个调用.
源码地址级联菜单
还有一个拆分比较细的,也可以看看级联菜单细分
有更好的方法也可以提供给我.
---------------------------------2018.4.8更新--------------------------------------------
1.添加路由跳转
在级联导航的最后一层才有跳转的链接
所以,我们判断path的值就行
<li class="cascader-item">
<p @click="router(data.path)">{{ data.label }}</p>
</li>
router(path){
if(path!=undefined){
console.log("path11111111",path);
this.$router.push("/hello")
}
},
2.清空this.childMenu问题
上边最后一点
我们添加了一个空的100%div,当鼠标在这个空白区域时,清空。
这个时所有都布局高度都是100%时,没有问题,但是高度为一定值时,就有问题
(li 标签有高度,100%div会超出他的父级高度)鼠标超出绿色区域,菜单就应该关闭,但是红色区域超出,导致不关闭
解决方法
在 ul上添加方法
handlemouseover(e){
console.log("this is over",e)
if(e.srcElement.nodeName == "LI"){
return
}else{
this.currentIndex = -1;
this.childMenu=[];
}
},
git代码地址级联菜单细分