uniapp 分类左右联动

我实现了左右联动,但是如果数据过多的情况,

我想在每一个分类里进行上拉和下拉加载,一次十条哪种

确定加载完了在去加载完下一个分类

效果


 

代码

<template>
  <view class="shopContents flex">
    <view class="left flex-shrink boxOverHide">
      <!-- :scroll-into-view="leftScrollId + currentActive" -->

      <scroll-view
        scroll-y="true"
        enable-flex
        :scroll-top="leftScrollTop"
        scroll-with-animation
        :scroll-into-view="leftScrollId + currentActive"
        id="leftScroll"
        class="scroll-left h-100">
        <view
          class="item flexCenter flex-column scrollLeftItem"
          :class="{ activeItem: currentActive === index }"
          :id="leftScrollId + index"
          @tap="changeLeftItem(index, item)"
          v-for="(item, index) in list"
          :key="index">
          <view class="imgBox"></view>
          <view class="txt mt-19">{{ item.txt }}</view>
        </view>
      </scroll-view>
    </view>
    <view
      class="right flex-1 boxOverHide"
      @tap="computedRightDom">
      <scroll-view
        id="rightScroll"
        scroll-y="true"
        scroll-with-animation
        :scroll-top="rightScrollTop"
        @scroll="rightScroll"
        @scrolltolower="rightScrolltolower()"
        class="scroll-left h-100">
        <view
          class="item scrollRightItem"
          v-for="(item, index) in list"
          :key="index">
          <view class="item">
            <view class="title">{{ item.txt }}</view>
            <view class="child mt-19">
              <view
                class="childItem boxOverHide flex"
                v-for="(childItem, childIndex) in item.child"
                :key="childIndex">
                <view class="imgBox shrink"></view>
                <view class="contentsBox flex-1 flex flex-column j-sb">
                  <view class="titleBox text-center">
                    可口可乐碳酸饮料迷你罐
                    <br />
                    200mlx12罐整箱汽水原味
                  </view>
                  <view class="botBox flex a-center j-sb">
                    <view class="priceBox flex">
                      <view class="icon">¥</view>
                      <view class="num">32.00</view>
                    </view>
                    <view class="addBtn"></view>
                  </view>
                </view>
              </view>
            </view>
          </view>
        </view>
      </scroll-view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      currentActive: 0,
      leftScrollId: "leftScrollId",
      rightScrollId: "rightScrollId",
      list: [],

      rightDoms: [],
      rightScrollTop: 0,

      leftDoms: [],
      leftScrollTop: 0,
      leftScrollDom: {},
    };
  },

  watch: {
    currentActive(newV, oldV) {
      return;
      // 用于监听给滚动到中间,没有需求就算了
      const index = this.currentActive;
      const screenHeight = this.leftScrollDom.height;
      // 获取选中元素的位置
      const { top, height } = this.leftDoms[index];
      // 计算滚动的距离,使选中元素居中
      this.$nextTick(() => {
        this.leftScrollTop = top + height / 2 - screenHeight / 2;
      });
      console.log("change index", this.leftScrollTop);
    },
  },

  mounted() {
    this.initData();
    setTimeout(() => {
      this.$nextTick(() => this.computedDom());
    }, 0);
  },
  methods: {
    computedDom() {
      const query = uni.createSelectorQuery().in(this);
      const options = {
        rect: true,
        size: true,
      };
      query
        .selectAll(".scrollRightItem")
        .fields(options, (arr) => {
          let pageTop = arr[0].top;
          this.rightDoms = arr.map((data) => ({
            top: data.top - pageTop,
            height: data.height,
          }));
        })
        .exec();
      query
        .selectAll(".scrollLeftItem")
        .fields(options, (arr) => {
          let pageTop = arr[0].top;
          this.leftDoms = arr.map((data) => ({
            top: data.top - pageTop,
            height: data.height,
          }));
        })
        .exec();
      query
        .select("#leftScroll")
        .fields(options, (data) => {
          console.log(data);
          this.leftScrollDom = data;
        })
        .exec();
    },
    initData() {
      for (let i = 0; i < 20; i++) {
        let child = [];
        for (let j = 0; j < 4; j++) {
          child.push({
            txt: `分类-${i}  child-${j}`,
          });
        }
        this.list.push({
          txt: `分类-${i}`,
          child,
        });
      }
    },
    changeLeftItem(index, item) {
      this.currentActive = index;
      this.rightScrollTop = this.rightDoms[index].top;
    },
    rightScroll(e) {
      const top = e.detail.scrollTop;
      const arr = this.rightDoms;
      arr.forEach((item, index) => {
        if (top > item.top) {
          if (this.currentActive < index) return (this.currentActive = index);
        }
        if (top < item.top) {
          if (this.currentActive > index) return (this.currentActive = index);
        }
      });
    },
    rightScrolltolower() {
      console.log("到底了");
      this.currentActive = this.list.length - 1;
      this.leftScrollTop = 0;
    },
  },
};
</script>
<style lang="scss" scoped>
.shopContents {
  height: calc(100vh - 673rpx);

  .left {
    width: 154rpx;
    background-color: #fff;

    .item {
      width: 154rpx;
      height: 173rpx;
      &.activeItem {
        background: #f7f7f7;
        border-radius: 19rpx 0rpx 0rpx 19rpx;
        .txt {
          font-weight: 600;
          color: #f2981d;
        }
      }
      .imgBox {
        width: 92rpx;
        height: 92rpx;
        background-color: pink;
      }
      .txt {
        height: 23rpx;
        font-size: 23rpx;
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
        color: #333333;
        line-height: 23rpx;
      }
    }
  }

  .right {
    padding: 0 38rpx;
    .item {
      .title {
        padding-top: 38rpx;
        height: 27rpx;
        font-size: 27rpx;
        font-family: PingFangSC-Semibold, PingFang SC;
        font-weight: 600;
        color: #999999;
        line-height: 27rpx;
      }
      .child {
        .childItem {
          height: 192rpx;
          padding: 19rpx;
          margin-bottom: 19rpx;
          border-radius: 19rpx;
          background-color: #fff;

          .imgBox {
            width: 154rpx;
            height: 154rpx;
            background-color: green;
          }
          .contentsBox {
            margin-left: 19rpx;
            .titleBox {
              height: 69rpx;
              font-size: 23rpx;

              font-family: PingFangSC-Semibold, PingFang SC;
              font-weight: 600;
              color: #333333;
              line-height: 35rpx;
            }
            .botBox {
              .priceBox {
                color: #f2981d;
                .icon {
                  height: 23rpx;
                  font-size: 23rpx;
                  font-family: DINPro-Black, DINPro;
                  font-weight: 900;
                  color: #f2981d;
                  line-height: 23rpx;
                }
                .num {
                  height: 35rpx;
                  margin-left: 3rpx;
                  font-size: 35rpx;
                  font-family: DINPro-Black, DINPro;
                  font-weight: 900;
                  color: #f2981d;
                  line-height: 35rpx;
                }
              }
              .addBtn {
                width: 35rpx;
                height: 35rpx;
                background: #f2981d;
              }
            }
          }
        }
      }
    }
  }
}
</style>

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值