仿某幸咖啡小程序菜单栏之-左右菜单联动

2,001 阅读2分钟

前言

前段时间练手,写了这个小demo,因为觉得很多电商类、外卖类的程序都用的到,所以在这里跟大家交流一下。如果有更好的实现方法,也可以带带我。

这里有2个功能点:

  • 点击左侧分类标签的时候,右边滚动到相对应的盒子的区域
  • 右边滚动的时候,以顶部为点,滚动到哪个分类,左边就会滚动到对应的标签

先上效果图吧:

基本思路

因为微信没有锚点这东西,右边商品列表使用的是scroll-view原生组件,只能设置它的scroll-top

wxml代码块:

<my-swiper backgroundArr="{{backgroundArr}}" imgHeight="{{imgHeight}}"></my-swiper>

<view class="main">
	<scroll-view class="left" scroll-y="true" scroll-into-view="left{{leftId}}">
		<view id="left{{item.id}}" bindtap="leftClick" data-myindex="{{index}}" class="scroll-view-item {{leftNum==index?'active':''}}" wx:for="{{arr}}" wx:key="*this">{{item.title}}</view>
	</scroll-view>
	<scroll-view class="right" scroll-y="true" scroll-into-view="right{{rightId}}" scroll-with-animation="true" bindscroll="rightScroll">
		<view id="right{{item.id}}" class="scroll-view-item box" wx:for="{{arr}}" wx:key="*this">
			<view class="title">{{item.title}}</view>
			<view class="content">
				<view wx:for="{{item.subArr}}" wx:key="*this" wx:for-item="subItem">
					<image src="{{subItem.imgSrc}}" mode="widthFix"></image>
					<text>{{subItem.imgDesc}}</text>
				</view>
			</view>

		</view>
	</scroll-view>
</view>

左侧的分类栏是通过获取给每个分类提前设置好的ID值,进行样式的切换。点左侧跟右侧进行联动,就需要给右边的每个盒子一个ID,让左边的ID和右边ID还有左边的点击获取当前值都相等,就可以实现左侧的联动。

右侧的联动就需要获取到每个盒子的头部距离顶部的距离,然后把他们放到一个数组里,在右侧的事件中去遍历数组,同时获取我们滚动的距离跟数组中的盒子之间的值做判断,判断我们滚动了第几个盒子的范围内,然后就把相应的数组赋给左边。

js代码块:

Page({
  data: {
    backgroundArr: [
      "/images/banner/menubanner1.jpg",
      "/images/banner/menubanner2.jpg",
      "/images/banner/menubanner3.jpg",
    ],
    imgHeight: 520,
    arr: [],
    leftNum: 0,
    // 左侧ID
    leftId: 0,
    // 右侧ID
    rightId: 0,
    //box盒子高度数组
    boxheight: [],
  },
  // 左侧点击
  leftClick(e) {
    this.setData({
      leftNum: e.currentTarget.dataset.myindex,
      leftId: e.currentTarget.dataset.myindex,
      rightId: e.currentTarget.dataset.myindex
    })
  },
  // 右侧滚动
  rightScroll(e) {
    let st = e.detail.scrollTop
    let boxarray = this.data.boxheight
    let _this = this
    for (var i = 0; i < boxarray.length; i++) {
      if (st >= boxarray[i] - 10 && st < boxarray[i + 1] - 10) {
        _this.setData({
          leftNum: i,
          leftId: i
        })
        return;
      }
    }
  },
  //onLoad的生命周期 
  onLoad: function () {
    wx.cloud.callFunction({
      name: "getmenuData"
    }).then(res => {
      this.setData({
        arr: res.result.data[0].arr
      })
      this.computedHeight();
    })
  },
  // 生命周期onReady(类似于mounted)
  computedHeight: function () {
    const _this = this;
    setTimeout(() => {
      //专门用来储存高度的
      let heightArr = [0]
      // 一开始的初始值
      let baseNum = 0
      const query = wx.createSelectorQuery()
      query.selectAll('.box').boundingClientRect()
      query.selectViewport().scrollOffset()
      query.exec(function (res) {
        res[0].map(va => {
          baseNum += va.height
          heightArr.push(baseNum)
        })
        _this.setData({
          boxheight: heightArr
        })
      })
    }, 600);
  }
})

项目地址:

整个小程序的代码放在gitee仓库:gitee.com/wang_xiaohu…