vue3实现商城左右联动数据---BScroll(vue3代码复制就能用)

对于通过向下滚动到底部,然后网络请求加载下一个类别的数据这个功能已经实现了的,需要的朋友私聊我,目前这里是写死的
在这里插入图片描述 ----------在这里插入图片描述

<template>
  <section class="box">
    <div class="head">联动数据</div>
    <div class="content">
      <div class="left" ref="left">
        <ul>
          <li
            v-for="(item, index) in leftList"
            :key="item"
            :class="{ current: currentIndex == index }"
            @click="selectItem(index, $event)"
          >
            <span class="left-item">{{ item }}</span>
          </li>
        </ul>
      </div>
      <div class="right" ref="right">
        <ul>
          <li
            class="right-item right-item-hook"
            v-for="item in rightList"
            :key="item.name"
          >
            <div v-if="item.content[0]" class="tip">{{ item.name }}</div>
            <ul>
              <li
                v-for="num in item.content"
                :key="num.name"
                @click="clickHandle(num)"
              >
                <div>{{ item.name + num }}</div>
              </li>
            </ul>
          </li>
        </ul>
      </div>
    </div>
  </section>
</template>

<script>
import { computed, onMounted, reactive, ref } from 'vue';
// BScroll中文文档 https://www.mianshigee.com/tutorial/better-scroll/1.md
import BScroll from 'better-scroll';
export default {
  name: 'betterScroll',
  setup() {
    let left = ref(null); // 左边 列表盒子
    let right = ref(null); // 右边 列表盒子
    let leftList = ref(['a', 'b', 'c', 'd', 'e', 'f']);
    let rightList = reactive([
      {
        name: 'a',
        content: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
      },
      {
        name: 'b',
        content: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
      },
      {
        name: 'c',
        content: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
      },
      {
        name: 'd',
        content: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
      },
      {
        name: 'e',
        content: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
      },
      {
        name: 'f',
        content: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
      }
    ]);
    let listHeight = ref([]); // 右边数据高度集合
    let scrollY = ref(0); // 滚动距离
    let rights = ref(null); // 滚动 事件源
    const _initScroll = () => {
      // 给左边列表绑定点击事件 BScroll会默认覆盖浏览器默认的事件 得手动添加click=true
      new BScroll(left.value, {
        click: true
      });

      rights.value = new BScroll(right.value, {
        click: true,
        probeType: 3 //探针的效果,实时获取滚动高度
      });
      //rights这个对象监听事件,实时获取位置pos.y
      rights.value.on('scroll', (pos) => {
        scrollY.value = Math.abs(Math.round(pos.y));
      });
    };

    // 右边成员高度集合
    const _getHeight = () => {
      listHeight.value.splice(0, listHeight.value.length); //清空数组
      // 右边结构 li>ul>li  第一层li对应左边每个类型
      // 获取每个类型li元素实际高度
      let rightItems = right.value.getElementsByClassName('right-item-hook');
      let height = 0;
      // 设置第一项为0, 当scrollY.value = 0  默认展示第一条
      listHeight.value.push(height);
      for (let i = 0; i < rightItems.length; i++) {
        let item = rightItems[i];
        // 一个个累加左边对应右边li的高度
        height += item.clientHeight;
        listHeight.value.push(height);
      }
      // window.console.log(listHeight.value, rightItems, '222');
    };
    // 点击事件
    const selectItem = (index, event) => {
      //在better-scroll的派发事件的event和普通浏览器的点击事件event有个属性区别_constructed
      //浏览器原生点击事件没有_constructed所以当时浏览器监听到该属性的时候return掉
      if (!event._constructed) {
        return;
      } else {
        let rightItems = right.value.getElementsByClassName('right-item-hook');
        let el = rightItems[index];
        // 定位右边到对应的数据
        rights.value.scrollToElement(el, 0);
      }
    };
    // 给左边对应添加样式
    const currentIndex = computed(() => {
      // 循环listHeight高度
      for (let i = 0; i < listHeight.value.length; i++) {
        let height = listHeight.value[i];
        let height2 = listHeight.value[i + 1];
        // 当height2不存在的时候,或者落在height和height2之间的时候,直接返回当前索引
        // >=height,是因为一开始scrollY.value =0,height=0
        if (!height2 || (scrollY.value >= height && scrollY.value < height2)) {
          return i;
        }
        // listHeight.value 最后一个高度等于右边所有数据内容高度总和
        //  right.value.clientHeight 右边可视高度
        if (
          listHeight.value[listHeight.value.length - 1] -
            right.value.clientHeight <=
          scrollY.value
        ) {
          // // 左边条数比右边数据高度集合少一条,因为listHeight第一项是默认为0,滚动top默认为0 所以要减2
          return listHeight.value.length - 2;
        }
      }
      //如果listHeight.value没有的话,就返回0
      return 0;
    });
    const clickHandle = (val) => {
      alert(val);
    };
    onMounted(() => {
      window.console.log();
      _initScroll();
      _getHeight();
    });
    return {
      left,
      right,
      leftList,
      rightList,
      listHeight,
      scrollY,
      selectItem,
      currentIndex,
      clickHandle
    };
  },
  components: {}
};
</script>

<style scoped lang="scss">
.head {
  height: 100px;
  width: 100%;
  font-size: 32px;
  line-height: 100px;
  background: rgb(235, 163, 213);
}
.content {
  display: flex;
  position: absolute;
  height: 1200px;
  width: 100%;
  overflow: hidden;
  background: #eee;
}
.left {
  flex: 0 0 80px;
  width: 80px;
  background-color: #f3f5f7;
}
.left li {
  width: 100%;
  height: 100%;
}
.current {
  background-color: red;
  transition: 0.5s linear;
}
.left-item {
  display: block;
  width: 100%;
  height: 100px;
  line-height: 100px;
  text-align: center;
  border-bottom: 1px solid #ccc;
}
.right {
  flex: 1;
}
.tip {
  text-align: left;
  height: 50px;
  font-size: 32px;
  width: 100px;
  line-height: 50px;
  background: #ccc;
}
.right-item li {
  width: 100%;
  height: 143px;
  line-height: 100px;
  text-align: center;
  border-bottom: 1px solid rgb(10, 134, 235);
  box-sizing: border-box;
}
</style>

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值