先看完整代码:
<template>
<div>
<!-- 头部 -->
<van-sticky :offset-top="0">
<div class="header">
<van-icon name="chat-o" class="icon-one" />
<van-search
@click="search"
placeholder="请输入搜索关键词"
class="sousuo"
/>
<van-icon name="scan" class="icon-two" />
</div>
</van-sticky>
<!-- section部分 -->
<section class="section" ref="sec">
<div class="left" ref="left">
<ul class="ulone">
<li
class="lione"
v-for="(item, index) in leftList"
:class="{ lis_one_color: index == currentIndex }"
:key="index"
@click="leftClick(index)"
>
{{ item.name }}
</li>
</ul>
</div>
<div class="right" ref="right">
<ul class="rightulone">
<li class="lis" v-for="(i, ind) in rightList" :key="ind">
<div
v-for="(item, index) in i.app_category_items"
class="rightdiv"
:key="index"
>
<div class="rightdivtwo">
<div class="img">
<van-image :src="item.cover" />
</div>
<p>{{ item.name }}</p>
</div>
</div>
</li>
</ul>
</div>
</section>
<!-- 底部 -->
<tabbbar></tabbbar>
</div>
</template>
<script>
import BetterScroll from "better-scroll";
import Tabbbar from "../components/tabbbar.vue";
export default {
name: "VantClassification",
components: {
Tabbbar,
},
data() {
return {
list: [],
leftList: [],
rightList: [],
currentIndex: 0,
img: [],
rightBScroll: "",
leftBScroll: "",
allHeight: [], //承载右侧每一块高度值
flag: false,
};
},
created() {},
updated() {
if (!this.rightBScroll) {
this.$nextTick(() => {
this.leftBScroll = new BetterScroll(this.$refs.left, {
click: true,
probeType: 3,
});
console.log(this.leftBScroll);
this.rightBScroll = new BetterScroll(this.$refs.right, {
probeType: 3, // 是否会截流scroll事件
click: true, // 是否开启点击事件
// scrollY: true, // 是否开启Y轴滚动方向
// useTransition: false, // 防止iphone微信滑动卡顿
// bounce: true, // 是否启用回弹动画效果
// momentumLimitDistance: 5, // 符合惯性拖动的最小拖动距离
});
// console.log(this.rightBScroll);
let height = 0;
this.allHeight.push(height); // 先把0放在数组的开头
let uls = this.$refs.right.getElementsByClassName("lis");
Array.from(uls).forEach((v) => {
height += v.clientHeight;
this.allHeight.push(height); // 把每个li的高度放在新数组中
// console.log(this.allHeight);
});
// 右侧滚动距离
this.rightBScroll.on("scroll", (pos) => {
this.scrollY = Math.abs(Math.round(pos.y));
// console.log(this.scrollY);
for (let i = 0; i < this.allHeight.length; i++) {
if (
this.scrollY > this.allHeight[i] &&
this.scrollY < this.allHeight[i + 1]
) {
if (!this.flag) {
this.currentIndex = i;
console.log(this.currentIndex);
}
}
}
});
// 结束时距离
this.rightBScroll.on("scrollEnd", (pos) => {
//结束时触发事件获取一次位置,因为使用了模式2,惯性滚动不触发事件
this.scrollY = Math.abs(Math.round(pos.y));
this.flag = false;
});
});
}
},
mounted() {
let a = this.$refs.sec;
a.style.height = document.documentElement.clientHeight - 95 + "px";
this.getData();
},
computed: {},
methods: {
search() {
this.$router.push("/search");
},
// 请求数据
getData() {
this.$axios.get("/category/app_category").then((res) => {
console.log(res);
this.list = res.data.data;
// console.log(this.list);
let leftArr = [];
let rightArr = [];
this.list.forEach((v) => {
leftArr.push({
id: v.id,
name: v.name,
});
rightArr.push(v);
/* console.log(leftArr);
console.log(rightArr); */
});
this.leftList = leftArr;
// console.log(this.leftList);
// 右侧部分
this.rightList = rightArr;
// console.log(this.rightList);
});
},
leftClick(index) {
// console.log(index);
this.flag = true;
this.currentIndex = index;
this.rightBScroll.scrollTo(0, -this.allHeight[index], 300);
// console.log(this.allHeight[index]);
},
},
};
</script>
<style scoped>
.header {
background-color: #fff;
width: 100%;
height: 45px;
display: flex;
justify-content: space-between;
align-items: center;
}
.icon-one {
margin-left: 0.133333rem;
/* width: 7%; */
}
.sousuo {
width: 86%;
height: 45px;
}
.icon-two {
width: 7%;
margin-left: 0.133333rem;
}
/* section样式 */
.section {
margin-bottom: 50px;
display: flex;
overflow: hidden;
}
.ulone {
width: 2.6667rem;
overflow: hidden;
}
.lione {
font-weight: bold;
text-align: center;
font-size: 18px;
/* width: 100%; */
height: 50px;
line-height: 36px;
margin: 10px 0;
padding: 7px 0;
box-sizing: border-box;
}
.lis_one_color {
color: rgb(255, 102, 0);
border-left: 3px rgb(255, 102, 0) solid;
}
.right {
width: 7.3333rem;
overflow: hidden;
}
.rightulone {
width: 100%;
}
.rightdiv {
width: 33%;
/* height: 100px; */
/* background-color: blue; */
display: inline-block;
}
.img {
width: 100%;
height: 80px;
}
.rightdivtwo {
width: 100%;
padding: 0 5px;
box-sizing: border-box;
text-align: center;
}
</style>
主要绕一点的也就是中间的布局,之前是左右两边使用overflow:auto去写的
这里使用overflow:hidden
基本结构布局如下:
<section class="section" ref="sec">
<div class="left" ref="left">
<ul class="ulone">
<li class="lione">
</li>
</ul>
</div>
<div class="right" ref="right">
<ul class="rightulone">
<li>
<div class="rightdiv">
<div class="rightdivtwo">
<div class="img">
<van-image :src="item.cover" />
</div>
<p></p>
</div>
</div>
</li>
</ul>
</div>
</section>
css样式:
/* section样式 */
.section {
margin-bottom: 50px;
display: flex;
overflow: hidden;
}
.ulone {
width: 2.6667rem;
overflow: hidden;
}
.lione {
font-weight: bold;
text-align: center;
font-size: 18px;
/* width: 100%; */
height: 50px;
line-height: 36px;
margin: 10px 0;
padding: 7px 0;
box-sizing: border-box;
}
.lis_one_color {
color: rgb(255, 102, 0);
border-left: 3px rgb(255, 102, 0) solid;
}
.right {
width: 7.3333rem;
overflow: hidden;
}
.rightulone {
width: 100%;
}
.rightdiv {
width: 33%;
/* height: 100px; */
/* background-color: blue; */
display: inline-block;
}
.img{
width: 100%;
height: 80px;
}
.rightdivtwo {
width: 100%;
padding:0 5px;
box-sizing: border-box;
text-align: center;
}
使用better-scroll插件让布局可以滚动
if (!this.rightBScroll) {
updated () {
this.$nextTick(() => {
this.leftBScroll = new BetterScroll(this.$refs.left, {
click: true,
probeType: 3,
});
console.log(this.leftBScroll);
this.rightBScroll = new BetterScroll(this.$refs.right, {
probeType: 3, // 是否会截流scroll事件
click: true, // 是否开启点击事件
// scrollY: true, // 是否开启Y轴滚动方向
// useTransition: false, // 防止iphone微信滑动卡顿
// bounce: true, // 是否启用回弹动画效果
// momentumLimitDistance: 5, // 符合惯性拖动的最小拖动距离
});
console.log(this.rightBScroll);
});
},
}
之后获取最外层的循环的六个li
let height = 0;
this.allHeight.push(height);// 先把0放在数组的开头
let uls = this.$refs.right.getElementsByClassName('lis');
Array.from(uls).forEach(v => {
height += v.clientHeight
this.allHeight.push(height) // 把每个li的高度放在新数组中
// console.log(this.allHeight);
})
核心部分
if (!this.rightBScroll) {
this.$nextTick(() => {
this.leftBScroll = new BetterScroll(this.$refs.left, {
click: true,
probeType: 3,
});
console.log(this.leftBScroll);
this.rightBScroll = new BetterScroll(this.$refs.right, {
probeType: 3, // 是否会截流scroll事件
click: true, // 是否开启点击事件
});
let height = 0;
this.allHeight.push(height); // 先把0放在数组的开头
let uls = this.$refs.right.getElementsByClassName("lis");
Array.from(uls).forEach((v) => {
height += v.clientHeight;
this.allHeight.push(height); // 把每个li的高度放在新数组中
});
// 右侧滚动距离
this.rightBScroll.on("scroll", (pos) => {
this.scrollY = Math.abs(Math.round(pos.y));
// console.log(this.scrollY);
for (let i = 0; i < this.allHeight.length; i++) {
if (
this.scrollY > this.allHeight[i] &&
this.scrollY < this.allHeight[i + 1]
) {
if (!this.flag) {
this.currentIndex = i;
console.log(this.currentIndex);
}
}
}
});
// 结束滚动时距离
this.rightBScroll.on("scrollEnd", (pos) => {
this.scrollY = Math.abs(Math.round(pos.y));
this.flag = false;
});
});
}
为什么要加一个flag的状态?如果不加状态,会出现一个小bug。左边的点击事件会随着右边的滚动事件一起进行。也就是当我点击按钮让右边滚动时,左边的列表项会从上往下依次滚动到指定位置,加了这个状态后就完美的解决了冲突问题
修改前:
修改后: