vue结合better-scroll实现商品详情联动效果

better-scroll

ps:商品详情联动效果, 当滑动到某个位置时出现tab标签栏, 点击tab项时滑动到对应位置并激活当前类。

文章目录

    • better-scroll
      • 效果图
      • 安装better-scroll
      • template
      • 使用better-scroll
      • style

滑动元素吸顶.可参考

效果图

vue结合better-scroll实现商品详情联动效果_第1张图片

安装better-scroll

  • 安装: npm i better-scroll -S
  • 组件中引入: import BScroll from 'better-scroll'
  • better-scroll官网
  • 参考: better-scroll参数和方法

template

注意 content的高度不超过父容器的高度,是不能滚动的哦。


使用better-scroll

<script>
import BScroll from "better-scroll";

export default {
    name: "goodsDetail",
    data() {
        return {
            backgroundColor: "", //背景颜色
            hiddenTopBar: false, //是否显示tab
            categoryList: [{ name: "商品" }, { name: "详情" }], //tab标签
            currentIndex: 0, //当前元素下标
        };
    },
    mounted() {
        this.$nextTick(() => {
            // 实例化 BScroll
            this._initScrollY();

            //获取右侧tops
            this._initTops();
        })
    },
    destroyed() {
        this.$refs.listScroll && this.$refs.listScroll.destroy();
    },
    methods: {
        back() {
            this.$router.go(-1);
        },
        
        // 初始化better-scroll
        _initScrollY() {
            // 创建左侧滑动
            this.lefts = new BScroll(this.$refs.left, {
                probeType: 3,
                scrollY: true,
                click: true,
                useTransition: false, // 防止iphone微信滑动卡顿
                bounce: true,
                momentumLimitDistance: 5
            });
            //创建右侧滑动
            this.rights = new BScroll(this.$refs.right, {
                probeType: 2, //这里可以取4个值,具体参考官方文档
                click: true,
                useTransition: false // 防止iphone微信滑动卡顿
            });

            // 给右侧绑定的BScroll绑定监听事件,获取滑动过程中的位置
            this.rights.on("scroll", pos => {
                this.scrollY = Math.abs(Math.round(pos.y));

                let tops = this.$refs.boxItem.offsetTop;
                if (this.scrollY >= tops) {
                    this.hiddenTopBar = true;
                } else {
                    this.hiddenTopBar = false;
                }

                //设置背景颜色的透明度
                if (tops && this.scrollY) {
                    // this.backgroundColor = `rgba(250, 252, 255, ${this.scrollY / (this.scrollY + 44)})`;
                    this.backgroundColor = `${this.scrollY / (this.scrollY + 10)}`;
                } else if (this.scrollY == 0) {
                    this.backgroundColor = "transparent";
                }
            });

            //获取停下来的位置
            // 给右侧绑定的BScroll绑定监听事件,获取滑动结束时的位置
            this.rights.on("scrollEnd", pos => {
                this.scrollY = Math.abs(Math.round(pos.y));
                console.log(this.scrollY);
                for (let i = 0; i < this.tops.length; i++) {
                    if (
                        this.scrollY > this.tops[i] &&
                        this.scrollY < this.tops[i + 1]
                    ) {
                        this.currentIndex = i;
                        if (i > this.$refs.l_item.children.length - 3) {
                            var tmp =
                                i - (this.$refs.l_item.children.length - 3);

                            //当滚动到倒数第2个位置时左侧列表向上滚动一个距离
                            this.lefts.scrollToElement(
                                this.$refs.l_item.children[tmp],
                                100,
                                0,
                                0
                            );
                        }
                        if (i < this.$refs.l_item.children.length - 3) {
                            //当滚动到第3个位置时左侧列表向下滚动一个距离
                            this.lefts.scrollToElement(
                                this.$refs.l_item.children[0],
                                100,
                                0,
                                0
                            );
                        }
                    }
                }
            });
        },

        //获取当前li的top
        _initTops() {
            var tops = []; //定义一个空数组
            let top = 0;
            tops[0] = 0; //第一个li的坐标为0

            var lis = this.$refs.r_item.children; //获取到了每个li
            //Array.protoype.slice.call(lis) 将具有length属性的对象转成数组 lis可能是个对象
            Array.prototype.slice.call(lis).forEach((li, index) => {
                top = top + li.clientHeight; //当前的位置=上一个的位置+这个的高度
                tops.push(top);
            });

            this.tops = tops;
        },

        // 滑动某个点联动tab项
        selectItem(index, event) {
            this.currentIndex = index;

            this.clickEvent = true;
            if (!event._constructed) {
                return;
            } else {
                let rightItems = this.$refs.right.getElementsByClassName(
                    "right-item-hook"
                );
                let el = rightItems[index];
                this.rights.scrollToElement(el, 300);
            }
        },

        //nowIndex 点击联动对应位置
        nowIndex(scrollY) {
            /*
                如果滑动的位置在当前这个和下一个之间,返回的是这个的下标
                如:tops=[0,5,12,18,23]
                    如果scrollY=4  -----返回0
                        scrollY=8  -----返回1
            */
            for (let i = 0; i < this.tops.lenght; i++) {
                if (scrollY > this.tops[i] && scrollY < this.tops[i + 1]) {
                    this.currentIndex = i;
                }
            }
        },
    }
};
</script>

style


感谢.参考文章

你可能感兴趣的:(vue)