vue中better-scroll实现商品分类左右联动
结合
better-scroll插件实现商品分类左右联动交互方式。
前提准备
- 安装:
npm i better-scroll -S - 组件中引入:
import BScroll from 'better-scroll' - better-scroll官网
相关文章:
步骤:
- 先实现
左联右 - 再实现
右联左
效果图

1. 初始化数据
data() {
return {
currentIndex: 0, //当前选中index
scrollY: 0,
heightList: [0], //存储某个分类下的商品高度列表
flag: false, //标识是否选中
fixedTitle: '', //当前分类标题
tagList: [{"type": 1, "name": "全部"}, {"type": 2, "name": "热销"}], //分类列表
tagIndex: 0, //分类tag当前index
type: 1, // 1:全部 2:热销
categoryList: [ // 数据仅供测试,请自行copy多些来看效果
{
categoryId: 1,
name: "健康蔬菜",
goods: [
{
goodsName: '大个小番茄',
goodsSummary: '绿色小番茄',
goodsStock: 231,
goodsRetailPrice: 5.4,
goodsMarketPrice: 6.8,
// goodsMainImage: require('../../assets/images/icon/icon_1.png')
goodsMainImage: 'xxxxx'
},
{
goodsName: '新鲜小奶白菜',
goodsSummary: '清脆、鲜嫩蔬菜',
goodsStock: 134,
goodsRetailPrice: 3.8,
goodsMarketPrice: 5.5,
goodsMainImage: 'xxxxx'
},
]
},
{
categoryId: 2,
name: "时令蔬菜",
goods: [
{
goodsName: '大又甜地瓜',
goodsSummary: '自家种植放心品尝',
goodsStock: 344,
goodsRetailPrice: 6.5,
goodsMarketPrice: 8.4,
goodsMainImage: 'xxxxx'
},
{
goodsName: '精美套餐',
goodsSummary: '健康搭配新鲜蔬菜',
goodsStock: 1099,
goodsRetailPrice: 45.9,
goodsMarketPrice: 65.8,
goodsMainImage: 'xxxxx'
},
{
goodsName: '水果黄瓜',
goodsSummary: '可口脆嫩水果黄瓜',
goodsStock: 785,
goodsRetailPrice: 3.5,
goodsMarketPrice: 4.8,
goodsMainImage: 'xxxxx'
},
]
},
]
}
},
2. 实现左联动右
使用better-scroll中的
scrollToElement方法。
说明:
-
scrollToElement(el, time, offsetX, offsetY, easing)滚动到某个元素,
el(必填)表示 dom 元素,time表示动画时间,offsetX和offsetY表示坐标偏移量,easing表示缓动函数 -
scroll: 滚动时触发 -
scrollEnd:滚动结束时触发 -
destroy():销毁 better-scroll,解绑事件
- 目标元素区域上添加
ref属性标识。【右侧商品列表中标识ref="good"】
<!-- 右侧商品列表 -->
<section class="right_list fixeds" ref="r_list">
<div>
<div class='listsWrap'>
<ul class="goods-list" v-for="(outerItem, outerIdx) in categoryList" :key="outerIdx" ref="good">
<li class="goods-li bd" v-for="(item, index) in outerItem.goods" :key="index">
<!-- 自定义内容 -->
</li>
</ul>
</div>
</div>
</section>
- 在左边菜单中添加点击事件,滑动到右侧对应的位置。【这里定义
changeMenu事件】
<aside class="fixeds" ref="l_list">
<ul class="left-menu">
<li ref="l_item" :class="{'active': index === currentIndex}"
@click="changeMenu(index, item.name)" v-for="(item, index) in categoryList" :key="index">
<div class="cname" ref="cname">{{item.name}}</div>
</li>
</ul>
</aside>
changeMenu (index, name) {
this.currentIndex = index; //当前选中index
this.fixedTitle = name; //当前选中标题
//【-32 标题高度】 根据自身调整,如果不需要写0即可。
this.rightList.scrollToElement(this.$refs.good[index], 1000, 0, -32);
},
- 初始化
better-scroll中获取左菜单定义的ref属性,并开启点击事件
this.left = new BScroll(this.$refs.l_list, {
click: true, //是否开启点击事件
probeType: 3, //是否会截流scroll事件
})
3. 实现右联动左
- 监听右侧滚动时触发的距离,可通过
scroll事件来监听当前值。
这里右侧数据格式: 每个分类下有n个商品【即嵌套列表】
this.rightList = new BScroll(this.$refs.r_list, {
probeType: 3, // 是否会截流scroll事件
scrollY: true, // 是否开启Y轴滚动方向
click: true, // 是否开启点击事件
useTransition: false, // 防止iphone微信滑动卡顿
bounce: true, // 是否启用回弹动画效果
momentumLimitDistance: 5 // 符合惯性拖动的最小拖动距离
})
this.rightList.on('scroll', (res) => {
// 获取当前滚动距离
this.scrollY = Math.abs(Math.round(res.y));
})
- 定义数组,用来存储每个分类下的商品列表离顶部的距离
this.$refs.good.forEach((el, index) => {
this.heightList.push(el.offsetHeight + this.heightList[index]);
})
- 拿到
content滚动距离和每个子商品列表离顶部距离比较。更新左菜单index选中状态
遍历每个分类下的商品列表距离列表
for (let i = 0; i < this.heightList.length; i++) {
if (this.scrollY > this.heightList[i] && this.scrollY < this.heightList[i + 1]) {
if (!this.flag) {
this.currentIndex = i;
}
}
}
完整demo
完整js
<script>
import BScroll from "better-scroll";
export default {
data() {
return {
currentIndex: 0, // 当前选中index
scrollY: 0,
heightList: [0], // 存储某个分类下的商品高度列表
flag: false, // 解决是否选中当前分类index
fixedTitle: '', // 当前分类标题
tagList: [{"type": 1, "name": "全部"}, {"type": 2, "name": "热销"}], //分类列表
tagIndex: 0, //分类tag当前index
type: 1, // 1:全部 2:热销
categoryList: [ // 数据仅供测试,请自行copy多些来看效果
{
categoryId: 1,
name: "健康蔬菜",
goods: [
{
goodsName: '大个小番茄',
goodsSummary: '绿色小番茄',
goodsStock: 231,
goodsRetailPrice: 5.4,
goodsMarketPrice: 6.8,
goodsMainImage: 'xxxxx'
},
{
goodsName: '新鲜小奶白菜',
goodsSummary: '清脆、鲜嫩蔬菜',
goodsStock: 134,
goodsRetailPrice: 3.8,
goodsMarketPrice: 5.5,
goodsMainImage: 'xxxxx'
},
]
},
{
categoryId: 2,
name: "时令蔬菜",
goods: [
{
goodsName: '大又甜地瓜',
goodsSummary: '自家种植放心品尝',
goodsStock: 344,
goodsRetailPrice: 6.5,
goodsMarketPrice: 8.4,
goodsMainImage: 'xxxxx'
},
{
goodsName: '精美套餐',
goodsSummary: '健康搭配新鲜蔬菜',
goodsStock: 1099,
goodsRetailPrice: 45.9,
goodsMarketPrice: 65.8,
goodsMainImage: 'xxxxx'
},
{
goodsName: '水果黄瓜',
goodsSummary: '可口脆嫩水果黄瓜',
goodsStock: 785,
goodsRetailPrice: 3.5,
goodsMarketPrice: 4.8,
goodsMainImage: 'xxxxx'
},
]
},
]
}
},
mounted() {
this.fixedTitle = this.categoryList[0].name;
this.$nextTick(() => {
// 初始化better-scroll
this.scrollInit();
// 获取某个分类下商品列表离顶部距离
this.getCategoryListHeight();
})
},
methods: {
toCommTap(url) {
this.$router.push(url);
},
changeMenu (index, name) {
this.flag = true;
this.currentIndex = index;
this.fixedTitle = name;
//【-32 标题高度】 根据自身调整,如果不需要写0即可。
this.rightList.scrollToElement(this.$refs.good[index], 1000, 0, -32);
},
chageTag(index, type) {
this.tagIndex = index;
this.type = type;
console.log('切换标签');
},
/**
* 初始化
*/
scrollInit() {
this.left = new BScroll(this.$refs.l_list, {
click: true,
probeType: 3,
})
this.rightList = new BScroll(this.$refs.r_list, {
probeType: 3, // 是否会截流scroll事件
scrollY: true, // 是否开启Y轴滚动方向
click: true, // 是否开启点击事件
useTransition: false, // 防止iphone微信滑动卡顿
bounce: true, // 是否启用回弹动画效果
momentumLimitDistance: 5 // 符合惯性拖动的最小拖动距离
})
this.rightList.on('scroll', (res) => {
this.scrollY = Math.abs(Math.round(res.y));
for (let i = 0; i < this.heightList.length; i++) {
if (this.scrollY > this.heightList[i] && this.scrollY < this.heightList[i + 1]) {
if (!this.flag) {
this.currentIndex = i;
}
// 当滚动到倒数第2个位置时左侧列表向上滚动一个距离
if (i === this.$refs.l_item.length - 2) {
this.left.scrollToElement(this.$refs.l_item[1], 1000, 0, 0)
}
// 当滚动到倒数第3个位置时左侧列表向上下滚动一个距离
if (i === 2) {
this.left.scrollToElement(this.$refs.l_item[0], 1000, 0, 0)
}
// 获取当前分类标题
this.fixedTitle = this.$refs.cname[i].innerText;
}
}
})
this.rightList.on("scrollEnd", pos => {
//结束时触发事件获取一次位置,因为使用了模式2,惯性滚动不触发事件
this.scrollY = Math.abs(Math.round(pos.y));
this.flag = false;
})
},
/**
* 获取商品列表高度
*/
getCategoryListHeight() {
this.$refs.good.forEach((el, index) => {
this.heightList.push(el.offsetHeight + this.heightList[index]);
})
},
addToShopCart(item) {
// 添加购物车事件
},
}
}
</script>

本文介绍如何使用better-scroll插件实现商品分类的左右联动效果。通过初始化数据、实现左联动右及右联动左等步骤,详细展示了联动的具体实现过程。
5360

被折叠的 条评论
为什么被折叠?



