vue实现商品分类左右联动

vue中better-scroll实现商品分类左右联动

结合better-scroll插件实现商品分类左右联动交互方式。

文章目录

    • vue中better-scroll实现商品分类左右联动
      • 前提准备
      • 效果图
      • 1. 初始化数据
      • 2. 实现左联动右
      • 3. 实现右联动左
      • 完整demo

前提准备

  • 安装: npm i better-scroll -S
  • 组件中引入: import BScroll from 'better-scroll'
  • better-scroll官网

相关文章:

better-scroll监听元素吸顶

better-scroll商品详情联动


步骤:

  • 先实现左联右
  • 再实现右联左

效果图

vue实现商品分类左右联动_第1张图片


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方法。

说明:

  1. scrollToElement(el, time, offsetX, offsetY, easing)

    滚动到某个元素,el(必填)表示 dom 元素,time 表示动画时间,offsetXoffsetY 表示坐标偏移量,easing 表示缓动函数

  2. scroll: 滚动时触发

  3. scrollEnd:滚动结束时触发

  4. 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>

你可能感兴趣的:(vue,公众号,better-scroll使用,vue实现商品分类左右联动,vue商品列表联动,scrollToElement,vue商品分类菜单联动)