微信小程序> 小程序:模仿美团商品列表

小程序:模仿美团商品列表

浏览量:2625 时间: 来源:weixin_34082789

最近需求是做一个类似外卖软件的商品列表,左边类型标题栏一个滚动区域右边商品栏一个滚动区域这样子,两边的滚动是互相响应的。

搜了一下github,小程序好像还没有人开源出这个轮子来,当然安卓,ios,js这样的也是有的。所以就写了个demo~


实现功能

右边商品栏滚动到不同区域时:

1,左边类型标题栏会自动切换选中,并且滚动到中间位置。

2,最上标题切换。

点击左边标题栏一项时:

1,右边商品栏滚动到响应区域,标题切换。


备注

1,这里我用了wepy框架。其实这根框架没有一点关系,只不过我懒惰费事改回原生而已。wepy对象就相当于原生的wx对象,然后repeat其实就是个循环,没其他了。

2,存在的问题还是有的,虽然处理了,但是还是不清楚为什么会这样。scroll-top属性是不会跟随scroll-view滚动的而改变的,所以要自己手动改变,例如本来默认是0的,当你滑动到最底的时候他的值还是0,所以我每次滚动前先将scroll-top设置成目前值+0.00001(先做一个超级不明显的改变),再做赋值,这样就不会出现不生效的情况,但是不支持同步赋值,例如我先设置为0再设置设置成1,也是不生效的,所以我这里用了setTimeout异步了一下,就生效了。


实现思路

  • 其实就两个事件,一个右边商品栏的滚动事件,一个就是左边标题栏的每一项的点击事件
  • 初始化拿到数据的时候计算高度,距离,添加到每一项。
  • 用的是scroll-view组件 然后通过改变scroll-top属性来控制滚动区域滚动,至于为什么我没有用scroll-into-view,上面说到了目前值+0.00001,scroll-into-view传的是id,试过改成一个不存在的id没结果是不起作用的,所以我还是选择用scroll-top。


实现代码

data

data = {  goodsList: [    {      title: '类型1',      good: ['0-1', '0-2', '0-3']    },    {      title: '类型2',      good: ['1-1', '1-2', '1-3', '1-4']    },    {      title: '类型3',      good: ['2-1', '2-2', '2-3']    },    {      title: '类型4',      good: ['3-1', '3-2', '3-3']    },    {      title: '类型5',      good: ['4-1', '4-2', '4-3']    },    {      title: '类型6',      good: ['4-1', '4-2', '4-3']    },    {      title: '类型7',      good: ['4-1', '4-2', '4-3']    },    {      title: '类型8',      good: ['4-1', '4-2', '4-3']    },    {      title: '类型9',      good: ['4-1', '4-2', '4-3']    },    {      title: '类型9',      good: ['4-1', '4-2', '4-3']    },    {      title: '类型9',      good: ['4-1', '4-2', '4-3']    },    {      title: '类型9',      good: ['4-1', '4-2', '4-3']    },    {      title: '类型9',      good: ['4-1', '4-2', '4-3']    }  ],  inScroll: 0, // 滚动子项id  scrollTop: 0.00001, // 商品栏离顶部距离  typeTop: 0.000001, // 类型导航栏离顶部距离  // 屏幕高度  windowHeight: 0, // 获得可用窗口高度  goodsType: null // 商品栏上面固定的标题}复制代码

  1. methods

methods = {  /**   * 点击左边的标题栏的一项,把那一项的序号传进来就完事了   * @param index   */  toScrollItem (index) {    this.scrollTop = this.scrollTop += 0.00001    setTimeout(() = {      this.scrollTop = this.goodsList[index].top.begin      this.$apply()    })  },  /**   * 这里监听商品栏滚动条   * @param detail   */  handleScroll({detail}) {    // 每次滚动都需要循环匹配,找寻滚动条到达那个区域,匹配到了或者到最后了就停止,是真的蛋疼。    for (let i = 0; i  this.goodsList.length; i += 1) {      // 进入循环了,这个商品列表的数组是经过加工的,在初始化的时候计算了每个种类项区域(top)和左边标题(typeTop)离顶部距离。      let v = this.goodsList[i]      // 如果滚动条与顶部的距离 = 这一项开头的与顶部的距离  这一项结尾与顶部的距离,那么现在正显示的就是这个区域了。      if (detail.scrollTop = v.top.begin && detail.scrollTop  v.top.end) {        // 记录下现在显示的是第几个区域。        this.inScroll = i        // 位于商品栏区域上面的标题跟着变成现在显示的区域。        this.goodsType = v.title        // 左边标题栏也跟着滚动到,如果可以(看标题栏有多长囖),将对应的区域移到中间。        this.typeTop = v.typeTop        // 匹配到了,并且做完该做的东西就跳出循环,免得他继续匹配。        break      }    }  }}复制代码

onLoad

async onLoad() {  // 制作顶部距离,盒子高度,子项滚动id属性。  let [top, typeTop] = [0, 0]  this.goodsList.map((v, i) = {    // 这个商品栏区域总高度,因为每个子项高度都是固定的,x长度就是他的总高度。    this.goodsList[i].height = (v.good.length * 200 + 30)    // 计算这个商品栏的开头和结尾离头部的距离,就是此区域的位置,用来判断目前显示区域的。    // top就是这个区域开头与滚动区顶部的位置    this.goodsList[i].top = {begin: top, end: top + (v.good.length * 200 + 30)}    // 计算此项商品标题在商品类型标题栏的高度    this.goodsList[i].typeTop = typeTop    // 计算之后这个top就自增一个上一个区域的总高度的单位    top += (v.good.length * 200 + 30)    // 左边标题栏也自增一个固定长度单位,可以改的 ,看样式定义多少    typeTop += 100  })  // 获取屏幕总高度  const {windowHeight} = await wepy.getSystemInfoSync()  this.windowHeight = windowHeight  //  this.goodsType = this.goodsList[0].title}复制代码

view

template  view class="goods" style="height: {{windowHeight}}px"    !--种类栏--    scroll-view      scroll-y      class="goods_type_list"      scroll-with-animation      scroll-top="{{typeTop  (windowHeight/2) ? (typeTop - (windowHeight/2)) : 0}}"          repeat for="{{goodsList}}"        view class="goods_type_item {{inScroll === index ? 'active' : ''}}"              @tap="toScrollItem({{index}})"          {{item.title}}        /view      /repeat    /scroll-view    !--商品栏--    view class="goods_list"      view class="goods_type_fixed goods_type_title"{{goodsType}}/view      scroll-view scroll-y                   scroll-top="{{scrollTop}}"                   scroll-with-animation                   bindscroll="handleScroll"        repeat for="{{goodsList}}"          view class="scroll_item"            view class="goods_type_title" wx:if="{{index !== 0}}"title:{{item.title}}/view            view class="goods_type_title" wx:else/view            repeat for="{{item.good}}"              view class="goods_item"{{item}}/view            /repeat          /view        /repeat      /scroll-view    /view  /view/template复制代码

style

style  .goods{    position: relative;  } .goods_item{    background: ffd900;    height: 200px;  } .goods_type_item{   height: 70px; } .scroll_item:nth-last-child(1){   min-height: 100.1%; }  scroll-view{    height: inherit;  }  .goods_type_item.active{    background: ffd888;  }  .goods_type_title{    height: 30px;    line-height: 30px;    font-size: 17px;    background-color: white;    width: 100%;  } .goods_type_list{   position: absolute;   width: 100px; }  .goods_list{    margin-left: 100px;height: inherit;position: relative;  }  .goods_type_fixed{    position: absolute;top: 0;z-index: 1;  }/style复制代码


然后做出来就是这样样子的


各位大佬如果觉得我有什么写的不对的地方或者更有方案的建议,可以私信或者评论告诉我,我这个是比较粗糙的版本,只是一个基本的实现思路,第一次写练练文笔请多包涵。


小程序

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

产品经理

手机 : 13312967497

擅长 : 小程序流量变现

扫码领取礼包

最新资讯

热门模板

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎