这样一个组件的话我们是经常都能看到的,也经常都会用到,日常积累
首先从我们的布局开始,布局当然是越简单越好。我们是可以看到左边一个列表,固定不变的,右边是一个弹出菜单,菜单根据左边的每一栏获得不同的值,展示不同的内容,当然我这个gif图做得比较垃圾。大概明白这个意思就好
那么我看看这个布局怎么做
<template> <div class="m-menu"> <dl class="nav" @mouseleave='mouseleave'> //将方法绑定到父级 <dt>全部分类</dt> <dd > //这样我们就能根据当前的type去循环 <i :class="item.type" />第一个<span class="arrow" /> </dd> </dl> // 上面这个就是我们看到的左侧的菜单列表 <div> <template > // 这里放右侧的子类列表 <h4 >美食</h4> <span>烧烤</span> </template> </div> </div> </template>
布局就这样两块儿就可以了,然后看下数据结构
data() { return {
kind:'',
menu: [{ type: 'food', name: '美食', child:[{ // 这个child 就是我们右侧子类菜单需要展示的title和列表数据 title:'美食', child:['代金券','葡萄干','火锅','快餐','小吃'] }] }, { type: 'takeout', name: '外卖', child:[{ title:'外卖', child:['干锅','快餐','中餐','小炒','汤品'] }] }, { type: 'hotel', name: '酒店', child:[{ title:'酒店星级', child:['经济型','舒适型','三星','四星','五星'] }] }, { type: 'hotel', name: '酒店', child:[{ title:'酒店星级', child:['经济型','舒适型','三星','四星','五星'] }] }] } }
现在的话我们就可以去循环menu数据
<dd v-for='item in menu' :key='item.id'> // 首先获取到小图标的type值 然后获取name <i :class="item.type" />{{ item.name }} <span class="arrow" /> </dd>
紧接着我们得循环右侧的菜单详情
<div class="detail" v-if='kind' @mouseenter='sover' @mouseleave='sout'> <template v-for="(item,index) in curdetail.child"> //curdetail 是我们遍历鼠标移入的是哪个左侧的item,然后添加 <h4 :key="index">{{ item.title }}</h4> <span v-for="list in item.child" :key="list.id">{{ list }}</span> </template> </div>
现在需要做的就是遍历数组,这里使用了原生的filter方法过滤数组
computed: { curdetail:function(){
return this.menu.filter((item)=>item.type === this.kind)[0] // 利用filter过滤了item数组,拿到type并添加到kind,这样就拿到了侧边菜单的数据
} },
现在这个就成了,接下来需要实现鼠标移入移出了,首先鼠标离开的时候
我们先定义一个事件
methods: { mouseleave(){
let index = this;
index._timer=setTimout(()=>{
index.kind='' 鼠标离开的时候我们在200毫秒后清空kind,kind就是我们通过过滤获取到右侧菜单数据,这个方法是绑定到右侧导航栏上的
},200)
}}
上面我们过滤了数组,现在我们需要将过滤的数组使用了,判断鼠标移入的是哪个i
enter:function(e){ //鼠标移入 获取当前 i上面的type值 然后赋值给kind this.kind=e.target.querySelector('i').className //这里使用了target.querySelector这个原生dom选择器 用来获取当前i的className,然后赋给当前的kind },
接下来还要处理下鼠标移入子级后,不能让子级菜单小时
sover:function(){ clearTimeout(this._timer) // 清除定时器 },
sout:function(){ // 当鼠标离开的时候 清空kind值
this.kind=''
}
,这样一个侧边菜单组件完成,完整代码如下
<template> <div class="m-menu"> <dl class="nav" @mouseleave="mouseleave"> <dt>全部分类</dt> <dd v-for="item in menu" :key="item.id" @mouseenter="enter" > <i :class="item.type" />{{ item.name }} <span class="arrow" /> </dd> </dl> <div v-if="kind" class="detail" @mouseenter="sover" @mouseleave="sout" > <template v-for="(item,index) in curdetail.child"> <h4 :key="index">{{ item.title }}</h4> <span v-for="list in item.child" :key="list.id">{{ list }}</span> </template> </div> </div> </template> <script> export default { data() { return { kind:'', //鼠标移入类型 menu: [{ type: 'food', name: '美食', child:[{ title:'美食', child:['代金券','葡萄干','火锅','快餐','小吃'] }] }, { type: 'takeout', name: '外卖', child:[{ title:'外卖', child:['干锅','快餐','中餐','小炒','汤品'] }] }, { type: 'hotel', name: '酒店', child:[{ title:'酒店星级', child:['经济型','舒适型','三星','四星','五星'] }] }, { type: 'hotel', name: '酒店', child:[{ title:'酒店星级', child:['经济型','舒适型','三星','四星','五星'] }] }] } }, computed: { curdetail:function(){ //判断当前数据 并遍历 return this.menu.filter((item)=>item.type === this.kind)[0] // 用 filer过滤item数组,并拿到type 然后添加到kind } }, methods: { mouseleave:function(){ //鼠标离开的时候 let self = this; self._timer = setTimeout(() => { self.kind = '' }, 150); }, enter:function(e){ //鼠标移入 获取当前 i上面的type值 然后赋值给kind this.kind=e.target.querySelector('i').className }, // 鼠标移入子级 sover:function(){ clearTimeout(this._timer) }, sout:function(){ this.kind='' } } } </script> <style scoped lang="scss"> @import "@/assets/css/index/index.scss"; </style>