移动端的菜单导航栏(展示式)一般有三种:
1.限量展示,末尾加‘更多’图标(杰出代表:支付宝)
适用于菜单项特别多,且能再次分类的。简化页面,点击‘更多’跳转菜单页,显示更清晰。(个人见解哈)
2.轮播式展示(不自动轮播)(杰出代表:美团、饿了么)
适用于最后一页菜单项数量大于等于单页满额数量一半的情况,不然显示出来不够‘友善’。(个人见解哈)
3.左右滑动展示(杰出代表:淘宝)
适用于最后一页菜单项数量小于等于甚至大于单页满额数量一半的情况。这种展示方式,我个人认为最完美了,除非说菜单项超级多。(个人见解哈)
由于个人偏好第三种展示方式,所以我们今天来说一下第三种菜单导航栏展示方式的实现。
Step1: 基本样式实现
作为一个前端人猿,这并不是个问题吧。
—我们可以暂时不考虑下方的分页条—
<!-- 仿淘宝首页中的的菜单分类导航 -->
<div class="pages-box classify">
<div class="classify-box" ref="menuList" @scroll="scrollEvent">
<div
class="classify-items"
v-for="(item, index) in classifyList"
:key="index"
>
<div class="item" v-for="(i, ind) in item" :key="ind">
<div class="pic">
<img :src="i.imageUrl" alt="" />
</div>
{{ i.title }}
</div>
</div>
</div>
</div>
.classify{
margin: 20px 5vw;
padding: 10px 0px;
/* border: 1px solid crimson; */
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
/****** 分类导航******/
.classify-box {
width: 90vw;
/* height: 200px; */
padding: 20px 0px;
/* margin: 20px 5vw; */
box-sizing: border-box;
display: flex;
flex-direction: row;
/* align-items: center; */
overflow-x: scroll;
white-space: nowrap; /*不换行*/
}
.classify-box::-webkit-scrollbar{
display: none;
}
.classify-items {
min-width: 20%;
/* height: 100%; */
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: center; */
}
.item {
/* width: 80px; */
/* height: 50%; */
margin: 5px 0px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.pic {
width: 100%;
height: 0px;
padding-bottom: 100%;
position: relative;
display: flex;
}
.pic img {
width: 100%;
height: 100%;
position: absolute;
}
Step2: 处理数据
// 一般我的获取到的数据这样的:
classifyList: [
{
id: 1,
imageUrl: require('../../assets/images/drinks-icon.png'),
title: '饮料',
url: ''
},
{
id: 2,
imageUrl: require('../../assets/images/entertainment-icon.png'),
title: '娱乐',
url: ''
},
{
id: 3,
imageUrl: require('../../assets/images/fruit-icon.png'),
title: '水果',
url: ''
},
{
id: 4,
imageUrl: require('../../assets/images/hospital-icon.png'),
title: '医院',
url: ''
},
{
id: 5,
imageUrl: require('../../assets/images/hotels-icon.png'),
title: '住宿',
url: ''
},
{
id: 6,
imageUrl: require('../../assets/images/seafood-icon.png'),
title: '海鲜',
url: ''
},
{
id: 7,
imageUrl: require('../../assets/images/snacks-icon.png'),
title: '零食',
url: ''
},
{
id: 8,
imageUrl: require('../../assets/images/surround-icon.png'),
title: '周边',
url: ''
},
{
id: 9,
imageUrl: require('../../assets/images/tour-icon.png'),
title: '旅游',
url: ''
},
{
id: 9,
imageUrl: require('../../assets/images/vegetable-icon.png'),
title: '蔬菜',
url: ''
},
{
id: 10,
imageUrl: require('../../assets/images/vegetable-icon.png'),
title: '蔬菜',
url: ''
}
]
但是这样的数据不利于我们布局,所以需要将数据分成2两两一组。
// 将1维数组转换为numArray维数组
// arr:需要处理的数组
// numArray:几个为一组
classifyListDeal (arr, numArray) {
let tempArray = []
for (let i = 0, k = -1; i < arr.length; i += 1) {
if (i % numArray === 0) {
k += 1
tempArray[k] = []
}
tempArray[k].push(arr[i])
}
this.classifyList = tempArray
console.log('处理后的classifyArray', this.classifyList)
},
Step3: 接下来就是来搞下方的分页条了。
分页条 = 轨道 + 滑块
轨道 给个固定的值(这里直接给了100px)。
滑块 根据 菜单栏的总长度与展示长度的比值 设置滑块长度
滑块滑动距离就与 滑块长度、菜单长度以及才懂滚动距离有关。
<!-- 分页器 -->
<!--分页器的父级:pages-box classify,兄弟:classify-box -->
<div class="classify-bar" :style="{'width':((classifyList.length - 5) / classifyList.length *100)*classifyList.length + 'px'}" v-if="classifyList.length > 5">
<div class="bar-track">
<div class="bar-thumb" :style="{'width':(5 / classifyList.length *100) + 'px','margin-left': thumbL + 'px'}"></div>
</div>
</div>
// 滚动事件
scrollEvent (e) {
let that = this
let menuList = that.$refs.menuList
let eleW = (1 - (that.classifyList.length - 5) / that.classifyList.length) *100
that.thumbL = eleW / (menuList.offsetWidth / menuList.scrollLeft)
}
/* 分页器 */
.classify-bar{
width: 100px;
height: 4px;
}
.classify-bar .bar-track{
width: 100%;
height: 100%;
border-radius: 4px;
background: darkseagreen;
overflow: hidden;
}
.classify-bar .bar-thumb{
height: 100%;
border-radius: 4px;
background:darkslategray;
}
实现效果: