vue实现商品分类左右联动
vue中better-scroll实现商品分类左右联动结合better-scroll插件实现商品分类左右联动交互方式。前提准备安装: npm i better-scroll -S组件中引入: import BScroll from 'better-scroll'better-scroll官网相关文章:better-scroll监听元素吸顶better-scroll商品详情联动步骤:先实现左联右再实
·
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>
更多推荐
已为社区贡献9条内容
所有评论(0)