微信小程序商城分类滚动列表锚点(左菜单右列表)

发布时间 2023-10-11 18:10:11作者: ℡北瞳少年、

1、TestScroll.wxml

<view class="content-box">
  <!-- 左侧分类 -->
  <scroll-view scroll-y scroll-with-animation class="left" style="width:245rpx;height:100%;background: #f2f2f2;" scroll-into-view='{{leftId}}'>
    <view id='left{{index}}' class="left-item {{activeKey===index?'active':''}}" wx:for="{{navData}}" data-index='{{index}}' wx:key='id' bindtap="onChange">
      <text class='name'>{{item.name}}</text>
    </view>
  </scroll-view>
  <!-- 滚动列表 -->
  <scroll-view class="right" scroll-y scroll-with-animation scroll-into-view="{{selectedId}}" bindscroll="changeScroll" style='height:100%;'>
    <!-- 每个分类 -->
    <view class="item subtitle" wx:for="{{goodslist}}" wx:key="id" id='type{{index}}'>
      <!-- 分类标题 -->
      <view class="type">【{{item.name}}】</view>
      <!-- 分类下的商品 -->
      <view class="item-list">
        <navigator class="list-item" wx:for="{{item.list}}" wx:for-item='key' wx:key="id">
          <!-- <image style="width: 100%; height: 180rpx;" src="{{key.imgurl}}" /> -->
          <view class="item-name">{{key.goods_name}}</view>
        </navigator>
      </view>
      <view wx:if="{{item.list.length===0}}" class="nodata">
        暂无商品
      </view>
    </view>
  </scroll-view>
</view>

2、TestScroll.wxss

.content-box {
  width: 100%;
  height: calc(100% - 108rpx);
  overflow-y: hidden;
  display: flex;
}
.content-box .left {
  height: 100%;
  overflow-y: scroll;
}
.content-box .left .left-item {
  width: 100%;
  padding: 20rpx;
  box-sizing: border-box;
}
.content-box .left .left-item .name {
  word-wrap: break-word;
  font-size: 28rpx;
  color: #323233;
}
.content-box .left .active {
  border-left: 6rpx #ee0a24 solid;
  background-color: #fff;
}
.content-box .right {
  flex: 1;
}
.content-box .right .item {
  position: relative;
  padding: 20rpx;
  background: #fff;
}
.content-box .right .item .type {
  padding: 5rpx;
  position: sticky;
  top: 0;
  background-color: aliceblue;
  z-index: 1;
}
.content-box .right .item .item-list {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 20rpx;
  text-align: center;
}
.content-box .right .item .item-list .item-name {
  color: #3a3a3a;
  font-size: 26rpx;
  margin-top: 10rpx;
}
.content-box .right .item .nodata {
  padding: 20rpx;
  color: #ccc;
}

3、TestScroll.js

 

Page({

  /**
   * 页面的初始数据
   */
  data: {
    // 分类列表
    navData: [
      { name: "奔驰C" },
      { name: "奔驰E" },
      { name: "雷克萨斯E200" },
      { name: "雷克萨斯E300" },
      { name: "宝马3系" },
      { name: "宝马5系" },
      { name: "奥迪Q5" },
      { name: "奥迪A6" },
      { name: "奥迪A8" },
      { name: "凯迪拉克CT4" },
      { name: "凯迪拉克CT5" },
      { name: "凯迪拉克CT6" },
      { name: "凯美瑞" },
      { name: "亚洲龙" },
      { name: "雅阁" },
      { name: "英诗派" },
    ],
    // 商品列表
    goodslist: [
      { 
        name: "奔驰C",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
          { goods_name: "来来来4" },
          { goods_name: "来来来5" },
        ]
      },
      { 
        name: "奔驰E",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
        ]
      },
      { 
        name: "雷克萨斯E200",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
          { goods_name: "来来来4" },
          { goods_name: "来来来5" },
          { goods_name: "来来来6" },
          { goods_name: "来来来7" },
        ]
      },
      { 
        name: "雷克萨斯E300",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
        ]
      },
      { 
        name: "宝马3系",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
          { goods_name: "来来来4" },
        ]
      },
      { 
        name: "宝马5系",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
        ]
      },
      { 
        name: "奥迪Q5",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
          { goods_name: "来来来4" },
          { goods_name: "来来来5" },
          { goods_name: "来来来6" },
          { goods_name: "来来来7" },
          { goods_name: "来来来8" },
          { goods_name: "来来来9" },
          { goods_name: "来来来10" },
        ]
      },
      { 
        name: "奥迪A6",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
        ]
      },
      { 
        name: "奥迪A8",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
        ]
      },
      { 
        name: "凯迪拉克CT4",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
          { goods_name: "来来来4" },
          { goods_name: "来来来5" },
          { goods_name: "来来来6" },
          { goods_name: "来来来7" },
          { goods_name: "来来来8" },
        ]
      },
      { 
        name: "凯迪拉克CT5",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
        ]
      },
      { 
        name: "凯迪拉克CT6",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
          { goods_name: "来来来4" },
          { goods_name: "来来来5" },
          { goods_name: "来来来6" },
          { goods_name: "来来来7" },
          { goods_name: "来来来8" },
          { goods_name: "来来来9" },
          { goods_name: "来来来10" },
          { goods_name: "来来来11" },
          { goods_name: "来来来12" },
          { goods_name: "来来来13" },
          { goods_name: "来来来14" }
        ]
      },
      { 
        name: "凯美瑞",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
        ]
      },
      { 
        name: "亚洲龙",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
          { goods_name: "来来来4" },
          { goods_name: "来来来5" },
          { goods_name: "来来来6" },
          { goods_name: "来来来7" },
          { goods_name: "来来来8" },
          { goods_name: "来来来9" },
          { goods_name: "来来来10" }
        ]
      },
      { 
        name: "雅阁",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
        ]
      },
      { 
        name: "英诗派",
        list: [
          { goods_name: "来来来1" },
          { goods_name: "来来来2" },
          { goods_name: "来来来3" },
        ]
      },
    ],
    // 左侧分类选中项 分类列表数组的下标
    activeKey: 0,
    // 计算出的锚点的位置
    heightList: [],
    // 右侧子元素的锚点
    selectedId: 'type0',
    // 左侧分类的锚点
    leftId: 'left0',
  },
  onShow() {
    this.selectHeight()
  },
  // 计算右侧每个锚点的高距离顶部的高
  selectHeight() {
    var _that = this;
    var list = [];
    const query = wx.createSelectorQuery();
    query.selectAll('.subtitle').boundingClientRect()
    query.exec((res) => {
      console.log("res-----",res[0]);
      res[0].forEach((item) => {
        list.push(item.bottom)
      })
      _that.setData({ heightList: list })
      console.log('heightList-------',list);
    })
  },
  changeScroll(e) {
    // 获取距离顶部的距离
    let scrollTop = e.detail.scrollTop;
    // 当前分类选中项,分类列表下标
    let { activeKey, heightList } = this.data;
    console.log('scrollTop-------',scrollTop);
    // 防止超出分类              判断滚动距离是否超过当前分类距离顶部高度
    if (activeKey + 1 < heightList.length && scrollTop >= heightList[activeKey]) {
      this.setData({
        // 左侧分类选中项改变
        activeKey: activeKey + 1,
        // 左侧锚点对应位置
        leftId: `left${activeKey + 1}`
      })
    }
    if (activeKey - 1 >= 0 && scrollTop < heightList[activeKey - 1]) {
      this.setData({
        activeKey: activeKey - 1,
        leftId: `left${activeKey - 1}`
      })
    }
  },
  onChange(event) {
    let index = event.currentTarget.dataset.index
    this.setData({
      activeKey: index,
      selectedId: "type" + index
    });
  },
})