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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_31126175/article/details/79139322

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

这个菜单,类似于那种树形菜单,用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代码地址级联菜单细分

猜你喜欢

转载自blog.csdn.net/qq_31126175/article/details/79139322
今日推荐