结合
better-scroll
插件实现商品分类左右联动交互方式。
npm i better-scroll -S
import BScroll from 'better-scroll'
相关文章:
better-scroll监听元素吸顶
better-scroll商品详情联动
步骤:
左联右
右联左
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'
},
]
},
]
}
},
使用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事件
})
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;
}
}
}
请下载
完整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>