微信小程序列表展示页面流程与优化

545 阅读2分钟

前言

在日常开发业务中,一个典型的场景就是数据展示页面,比如下图所显示的业务场景。

image.png

这是一个微信小程序开发的项目,主要功能是闲置物品的展示,这里涉及到瀑布流,上拉刷新、下拉加载、切换分类几个功能,本文主要是梳理在此需求的开发过程中的重点。

思路与代码整理

//js
Page({
  leftHight: 0,  // 记录瀑布流左边的高度
  rightHight: 0, // 记录瀑布流右边的高度
  limit:10,  // 每一次请求的数量
  page:1,  // 记录当前页数
  
  data:{
      loading:true, // 显示加载
      isNoData:false, // 是否当前没有数据
      goodClassList:[], // 导航列表
      goodClassChooseIndex:0, // 导航显示的位置,默认显示第一个【推荐】
      leftList: [], // 瀑布流左边的数据,
      rightList: [], // 瀑布流右边的数据
      isEnd:false, // 是否请求完所有的数据
  },
    // 获取闲置数据
  async _getUnusedData(){
    return new Promise(async (resolve,reject)=>{
      try {
        // 下面这行的getList是请求后端数据的接口,随便写的一个, 非本文上下文的代码,仅作示例
        let promise = getList({
          type_id:this.data.goodClassList[this.data.goodClassChooseIndex - 1].id
          skip:this.limit * (this.page -1) ,
          limit:this.limit
        })
        let res = await promise
        var allData = res.result.list;
        this.data.isEnd = allData.length < this.limit
        //定义两个临时的变量来记录左右两栏的高度,避免频繁调用setData方法
        var leftH = this.leftHight;
        var rightH = this.rightHight;
        var leftData = [];
        var rightData = [];
        for (let i = 0; i < allData.length; i++) {
          allData[i].height = height
          allData[i].width = width
          // 下面的 335 是瀑布流每一个item的宽度,根据需要设置
          let currentItemHeight = parseInt(Math.round(allData[i].height * 335  / allData[i].width));
          allData[i].height = currentItemHeight + "rpx"; //因为xml文件中直接引用的该值作为高度,所以添加对应单位
          if (leftH == rightH || leftH < rightH) { //判断左右两侧当前的累计高度,来确定item应该放置在左边还是右边
            leftData.push(allData[i]);
            leftH += currentItemHeight;
          } else {
            rightData.push(allData[i]);
            rightH += currentItemHeight;
          }
        }
        
        //更新左右两栏的数据以及累计高度
        this.leftHight = leftH
        this.rightHight = rightH
        let obj = {
          isEnd:this.data.isEnd,
          isNoData:leftH + rightH === 0
        }
        if(this.page == 1){
          this.setData(Object.assign(obj,{
            leftList: [leftData],
            rightList: [rightData],
          }))
        }else{
          this.setData(Object.assign(obj,{
            [`leftList[${this.page - 1}]`]: leftData,
            [`rightList[${this.page - 1}]`]: rightData,
          }))
        }
        this.page++
        resolve()
      } catch (error) {
        reject(error)
      }
    })
  },
  // 重置页面数据
  resetData(){
    this.page = 1
    this.data.leftList = []
    this.data.rightList = []
    this.leftHight = 0
    this.rightHight = 0
    this.data.isEnd = false
  },
  // 切换tab分类
  chooseGoodClass(e){
    let {index} = e.detail
    // 避免点击相同的分类
    if(index == this.data.goodClassChooseIndex) return
    // 展示loading效果
    this.showLoading()
    // 主要因为setData是异步的,直接这么写可以同步改变data中的代码(但是不会触发渲染,只有setData方法改变数据才会触发渲染,这里主要是为了方便后面的逻辑可以使用这里的数据)
    this.data.goodClassChooseIndex = index
    // 重置页面数据
    this.resetData()
    this._getUnusedData().then(res=>{
      // 关闭加载效果
      this.hideLoaidng()
    })
    // 这个setData其实也可以放在上一步_getUnusedData的setData一起放
    this.setData({
      goodClassChooseIndex:index
    })
  },
  // 下拉刷新
  onPullDownRefresh: function () {
    // 重置页面数据
    this.resetData()
    this._getUnusedData().then(res=>{
      wx.stopPullDownRefresh()
    })
  },
  // 上拉触底加载更多数据(下一页数据)
  onReachBottom: function () {
    // 如果已经请求完所有数据,不再发起请求
    if(this.data.isEnd) return
    Toast.loading({
      message: '加载中...',
      forbidClick: true,
      duration:0
    });
    this._getUnusedData().then(res=>{
      Toast.clear()
    })
  },
  showLoading(){
    this.setData({
      loading:true
    })
  },
  hideLoaidng(){
    this.setData({
      loading:false
    })
  }
})

下面是一些主要的wxml代码,主要提供思路

  // 加载组件
  <loading wx:if="{{loading}}"></loading>
  // 空数据组件
  <view wx:if="{{isNoData}}" class="no-data">
    <no-data></no-data>
  </view>
  // 列表展示
  <view class='lists'>
    <view class='left'>
      <block wx:for="{{leftList}}" wx:key="_id" wx:for-item="leftdatas">
        <block wx:for="{{leftdatas}}">
          <view class="list-item">
            这里是商品内容
          </view>
        </block>
      </block>
    </view>
    <view class='right'>
      <block wx:for="{{rightList}}" wx:key="_id" wx:for-item="rightdatas">
        <block wx:for="{{rightdatas}}">
          <view class="list-item">
            这里是商品内容
          </view>
        </block>
      </block>
    </view>
  </view>

上面就是这个商品列表页面需求一个完整的实现梳理,主要是自己在做项目的过程中常常遇到这样的需求,但是没有系统的整理过,每一次都要思考一会才能去下手,这次趁着这个机会做一个整理,也是给自己以后的开发做一个记录和参考。

这里的代码可能不全,主要是提供一个思路~