APP & program

微信小程序组件:列表(上滑加载、回到顶部)

2022-04-28  本文已影响0人  牛会骑自行车

列表需求:
1.上滑加载(分页);
2.回到顶部;
3.列表组件下拉刷新。

完成思路:
1.加载数据一般有两种方式:一种是采用数组方法,concat或push或es6的扩展运算符,总之就是把后面加载的数据与前面的拼接到一起;另一种方式性能较好,采用给数据的某一项赋值的方式,就不会一次性setData太大的数据以至于会报错(代码中两种方案都有写,不仅组件中的写法不一样,用到的页面中写法也不同,需要注意)。
2.回到顶部小箭头:页面滚动时监听容器的scrollTop,往下滑动时出现,接近0时消失;
3.回到顶部:点击小箭头时,使容器的scrollTop为0。
4.下拉刷新看scroll-view文档:
https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html

组件 👇
html ↓

<scroll-view 
  scroll-y 
  enhanced 
  bindscroll="scroll"
  bindscrolltolower="{{longPage?'':'moreData'}}" 
  scroll-top="{{scrollTop}}" 
  style="height: {{listHeight}}; "
  refresher-enabled 
  refresher-triggered="{{triggered}}" 
  bindrefresherrefresh="pullDownRefresh"
>
  <!-- 
    ↑ 参数官网都给了解释,总之都有用到,尼萌自己去查吧~~
   -->
  <slot></slot>
  <!-- ↑ 列表插槽儿~页面中放置数据的容器 -->
  <image src="/images/common/icon_totop.png" class="icon_totop" wx:if="{{iconTotopShow}}" bindtap="handleTotop"></image>
  <!-- ↑ 回到顶部的小箭头 -->
</scroll-view>

css ↓

.icon_totop {
  width: 72rpx;
  height: 80rpx;
  
  position: fixed;
  bottom: 30rpx;
  right: 20rpx;
}

js ↓

// components/scrollList/list.js

Component({
  properties: {
    // 是否分页:分页传false,不分页传true;默认需分页
    longPage: {
      type: Boolean,
      value: false 
    },
    // scroll-view的高度:官网有解释,如果使用scroll-view的话需要给其设置一个高度
    listHeight: String,
    // 接口相关的值
    interface: {
      type: Object,
        value: () => {
          return {
            url: "", // 接口地址
            params: {}, // 接口所需参数
            method: "" // 请求方法
          }
        }
    },
    // 下拉刷新所需的参数
    refresh: Boolean
  },
  data: {
    maxPage: null, // 最多页数
    data: [],
    iconTotopShow: false, // 回到顶部的图标显隐参数
    scrollTop: 0, // scroll-view滚动距离
    triggered: false, // 下拉刷新的提示
  },
  methods: {
    getData() {
      wx.showLoading({
        title: "加载中..."
      })
      let {
        url,
        method,
        params
      } = this.data.interface;
      // wx.httpWithoutToken是已经封装好的调取接口的方法,用wx.request也可以,用一样参数即可
      wx.httpWithoutToken(url, params, method).then(res => {
        if (res.code === 200 && res.success) {
          // 最大页码 = 数据总数 / 每页数据数
          let maxPage = res.totalCount / this.data.interface.params.pageSize;
          // 方法1:用数组方法先拼接再传值
          // let data = [...this.data.data,...res.content];
          // 方法2:只传递接口当前页的返回值
          let data = res.content;

          this.setData({
            maxPage,
            data
          })
          // 给父页面传值
          this.triggerEvent("update", {
            num: this.data.interface.params.pageNum, // 方法2中所需参数
            data
          })
        } else {
          wx.showToast({
            title: "暂无数据",
            icon: "none"
          })
        }
        wx.hideLoading();
        this.setData({
          triggered: false
        })
      })
    },
    moreData() {
      // 当前页码
      let num = this.data.interface.params.pageNum;
      // 最大页码存在且当前页码 >= 最大页码则数据全部展示完毕
      if (this.data.maxPage && num >= this.data.maxPage) {
        wx.showToast({
          title: "暂无数据",
          icon: "none"
        })
        return;
      }
      // 进行到这一步说明还可以继续请求,则页码+1
      num++;
      this.setData({
        "interface.params.pageNum": num
      })
      this.getData();
    },
    scroll(e) {
      // scroll-view的滚动距离
      let num = e.detail.scrollTop;
      // 如果这个距离小于一定的数据就让图标消失,反之图标出现
      let iconTotopShow = num <= 10 ? false : true;
      this.setData({
        iconTotopShow
      })
    },
    handleTotop() {
      // 通过给scroll-view的scrollTop赋值来让页面回到顶部
      this.setData({
        scrollTop: 0
      })
    }
  },
  pageLifetimes: {
    show() {
      this.getData();
    }
  },
  pullDownRefresh() {
    this.setData({
      ["interface.params.pageNum"]: 1,
      triggered: true
    })
    this.triggerEvent("clearList")
  },
  observers: {
    "refresh": function (val) {
      // observers会比show()生命周期先行
      // 通过判断有没有传入的interface来确定要不要调取接口
      if (JSON.stringify(this.data.interface) === '{}') return;
      // 初始化页面请求参数
      this.setData({
        'interface.params.pageNum': 1
      })
      // 再调取接口
      this.getData();
    }
  }
})

用到的页面 👇
html ↓

<!--views/list/list.wxml-->

<list interface="{{info}}" bindupdate="getData" refresh="{{refresh}}" listHeight="80vh">

  <view class="row bg_w" wx:for="{{list}}" wx:key="index">
    <view>{{item.name}}</view>
    <view>{{item.code}}</view>
  </view>

</list>

js文件 ↓

// views/list/list.js
Page({
  data: {
    info: {},
    list: [],
    refresh: false
  },
  initPage() {
    let info = {
      url: "selectOrder",
      method: "GET",
      params: {
        pageNum: 1,
        pageSize: 2
      }
    }
    this.setData({
      info
    })
  },
  getData(e) {
    // 方法1
    // this.setData({
    //   list: e.detail.data
    // })

    // 方法2
    let list = e.detail.data; // 组件里传出来的当前页数据
    let num = (e.detail.num - 1) * this.data.info.params.pageSize; 
    // 采用循环的方法给数组的每一项赋值
    list.forEach((item,index) => {
      this.setData({
        [`list[${num+index}]`]: item
      })
    })
  },
  onLoad: function (options) {
    this.initPage();
  },
  onPullDownRefresh: function() {
    // 下拉刷新时给refresh重新赋值
    this.setData({
      refresh: !this.data.refresh
    })
  }
})

还有一步引用组件,在当前页的json文件也可,app.json文件中全局引用也可~

tada~~~一个下拉刷新及上滑分页的微信小程序组件就完成啦~

上一篇下一篇

猜你喜欢

热点阅读