vue实现阿里云的左侧全部菜单

2022-07-08 10:39:32

首先,我们先看下阿里云的导航菜单的样式,对这个样式有一个了解。
这里写图片描述

这个菜单,类似于那种树形菜单,用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代码的样式

<divclass="cascader"><divclass="cascader-panel"><ul><liclass="cascader-item"><p>菜单一</p></li><liclass="cascader-item"><p>菜单二</p></li></ul><divclass="cascader-panel"><ul><liclass="cascader-item"><p>二级菜单_1</p></li><liclass="cascader-item"><p>二级菜单_2</p></li></ul><divclass="cascader-panel">
                ...</div></div></div></div>

其实就是cascader-panel里套着cascader-panel,自己套自己,就能用递归来实现.

cascaderpanel.vue文件

<template><divclass="cascader-panel"><ulv-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-panelv-if="childMenu && childMenu.length":data="childMenu"></cascader-panel></div></template><script>exportdefault{
  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><stylescoped>.cascader-panel{display: flex;height: 100%;}.isactive{color: blue;}li{width: 120px;cursor: pointer;}</style>

调用的时候,我是在app.vue中调用的.
代码如下:

<template><divid="app"><div@mouseenter="showall()"@mouseleave="showaleave()"><button>主菜单</button><divclass="cascader"v-show="show"><cascader-panel:data="menuList"></cascader-panel></div></div><p>111111111111111111111111111111111111111111111111111111111111111111111111</p></div></template><script>import CascaderPanelfrom"./components/CascaderPanel";exportdefault{
  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的值就行
这里写图片描述

<liclass="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代码地址级联菜单细分

  • 作者:潇蓝诺依
  • 原文链接:https://blog.csdn.net/qq_31126175/article/details/79139322
    更新时间:2022-07-08 10:39:32