今天上班写页面的时候,遇到有个需求是做一个可以横向滑动的菜单,类似于小程序里面的scroll-view组件。当然,如果只是简单的使用overflow-y:scroll去实现横向滑动菜单的话,体验不怎么好,因为在左右滑动的时候,总会有一种卡顿不流畅的感觉,为了改善这种状况,我决定引入一个滴滴前端团队的某位成员开源的滚动插件:better-scroll,不过这个插件使用比较多的场景还是在竖直方向的下拉列表里面,但今天我借助它来制作横向滑动的菜单,两种场景在使用上其实差不多,区别仅仅是横向滚动的场景中需要我们手动计算一下所有item的宽度之和,然后把总宽度赋值给它们的父容器,先看看最终的效果:
实现起来也不复杂,我把主要的代码贴出来,感兴趣的同学可以自己去尝试:
imgSearch.vue
<template>
<div class="imgSearch_container">
<div class="top_nav">
<Header title="图搜" />
<div class="search_nav">
<img class="search_img" src="../../assets/mock_imgs/goodsImg.png" />
<div class="categorys" ref="categorys">
<div class="categoty_list" ref="categoty_list">
<span
class="category_item"
ref="category_item"
:class="selectedCategoryIndex === index ? 'selected':''"
v-for="(item, index) in categorys"
@click="handleCategorySelect(index)"
:key="index">{{item.text}}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import BScroll from 'better-scroll'
import Header from '../../components/header/header.vue'
export default {
name: 'ImageSearch',
data() {
return {
categorys: [
{ id: 0, text: '全部' },
{ id: 1, text: '外套' },
{ id: 2, text: '裙子' },
{ id: 3, text: '衬衫' },
{ id: 4, text: '鞋子' },
{ id: 5, text: '牛仔裤' },
{ id: 6, text: '毛衣' },
],
// ...
selectedCategoryIndex: 0
}
},
components: {
Header
},
methods: {
// ...
handleCategorySelect (index) {
this.selectedCategoryIndex = index
}
},
mounted () {
let width = 0
for (let i = 0; i < this.categorys.length + 1; i++) {
width += this.$refs.category_item[0].getBoundingClientRect().width
}
this.$refs.categoty_list.style.width = width / parseFloat(document.documentElement.style.fontSize) + 'rem'
if (!this.scroll) {
this.scroll = new BScroll(this.$refs.categorys, {
scrollX: true,
scrollY: false,
momentum: false,
snap: {
loop: this.loop,
threshold: 0.3,
speed: 400
},
click: true
})
} else {
this.scroll.refresh()
}
}
}
</script>
<style lang="less" scoped>
@import './imageSearch.less';
</style>
imageSearch.less
.imgSearch_container {
.top_nav {
position: relative;
z-index: 100;
background: #fff;
}
.search_nav {
display: flex;
height: 107px;
border-top: 1px solid #E5E5E5;
border-bottom: 1px solid #E5E5E5;
.search_img {
width: 110px;
height: 110px;
}
.categorys {
width: 640px;
overflow: hidden;
.categoty_list {
display: flex;
width: 100%;
height: 128px;
}
.category_item {
flex-shrink: 0;
width: 116px;
height: 46px;
line-height: 46px;
border-radius: 25px;
border: 2px solid #9C9C9C;
font-size: 24px;
color: #9C9C9C;
text-align: center;
margin-top: 30px;
margin-left: 18px;
&.selected {
border-color: #F96388;
color: #F96388;
}
}
}
}
}