微信小程序下拉刷新、上拉加载

微信小程序官方没有给出具体的下拉刷新和上拉加载组件,我们可以基于小程序原生组件scroll-view的扩展与封装,实现简单的上拉加载、下拉刷新组件。

1. 封装组件

// components/customPullDown/index.js
Component({
	options: {
		multipleSlots: true
	},
	properties: {
		changeBoundaryThreshold: {
			type: Number,
			default: 45
		},
	},

	observers: {
		'changeBoundaryThreshold': function (val) {
			this.setData({
				changeBoundary: val
			})
		}
	},
	data: {
		refresherTriggered: false,
		changeBoundary: 45
	},
	methods: {
		onReachBottom (event) {
			this.triggerEvent('onReachBottom')
		},
		onRefresherRestore (event) {
			this.triggerEvent('onRefresherRestore')
		},
		onRefresherAbort (event) {
			this.triggerEvent('onRefresherAbort')
		},
		onPullDownRefresh (event) {
			this.setTriggerStatus(true)
			setTimeout(() => {
				this.setTriggerStatus(false)
			}, 1000)
		},
		setTriggerStatus (bool) {
			this.setData({
				refresherTriggered: bool
			})
			this.triggerEvent(bool ? 'onPullDownRefreshStart' : 'onPullDownRefreshEnd')
		}
	}
})

// components/customPullDown/index.json
{
    "component": true,
    "usingComponents": {}
}
<!-- components/customPullDown/index.wxml -->
<wxs module="pullDown" src="./pullDown.wxs"></wxs>
<view class="pull-down">
  <scroll-view
    refresher-enabled
    scroll-y
    scroll-with-animation
    refresher-default-style="none"
    refresher-triggered="{{refresherTriggered}}"
    bindrefresherpulling="{{pullDown.onContentPull}}"
    bindrefresherrestore="{{pullDown.onRestore}}"
    bindrefresherabort="{{pullDown.onAbort}}"
    bindrefresherrefresh="{{pullDown.onRefresh}}"
    bindscrolltolower="onReachBottom"
    class="scroll-box"
  >
    <view slot="refresher" class="custom-refresh-zone" data-threshold="{{changeBoundary}}">
      <view class="refresh-before-trigger">
        <view class="custom-refresh-zone-tips-loading">继续下拉刷新</view>
      </view>
      <view class="refresh-after-trigger">
        <view class="custom-refresh-zone-tips-loading">释放刷新</view>
      </view>
      <view class="refresh-loading">
        <view class="custom-refresh-zone-tips-loading">加载中...</view>
      </view>
    </view>
    <view>
      <view name="refresh-animation"></view>
      <slot name="content"></slot>
    </view>
  </scroll-view>
</view>
/* components/customPullDown/index.wxss */
.pull-down{
  width: 100%;
  height: 100%;
  position: relative;
}
.scroll-box{
  width: 100%;
  height: 100%;
}
.custom-refresh-zone{
  width: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}
.refresh-loading{
  width: 100%;
}

.custom-refresh-zone .refresh-before-trigger,
.custom-refresh-zone .refresh-after-trigger{
  display: none;
}
.custom-refresh-zone.refresher-before .refresh-before-trigger,
.custom-refresh-zone.refresher-after .refresh-after-trigger{
  width: 100%;
  display: block;
}
.custom-refresh-zone.refresher-before .refresh-loading,
.custom-refresh-zone.refresher-after .refresh-loading{
  display: none;
}
.custom-refresh-zone-tips-loading{
  display: flex;
  align-items: flex-start;
  justify-content: center;
  width: 100%;
  color: #bbb;
  font-size: 26rpx;
  padding: 10rpx;
}
.custom-refresh-zone-tips-loading.white {
  color: #fff;
}
/* components/customPullDown/pullDown.wxs */
var refresherBefore = 'refresher-before'
var refresherAfter = 'refresher-after'

function getComponent(name, selector) {
  return function(instance) {
    var state = instance.getState()
    return state[name] || (state[name] = instance.selectComponent(selector))
  }
}
var getCustomRefresher = getComponent('customRefresher', '.custom-refresh-zone')

module.exports = {
  onContentPull: function (event, ownerInstance) {
    var scrollY = event.detail.dy // 滚动距离
    // 根据滚动距离切换状态
    var customRefresher = getCustomRefresher(ownerInstance)
    var threshold = customRefresher.getDataset().threshold
    var isLargerThanTriggerThreshold = scrollY > threshold
    customRefresher
      .addClass(isLargerThanTriggerThreshold ? refresherAfter : refresherBefore)
      .removeClass(isLargerThanTriggerThreshold ? refresherBefore : refresherAfter)
  },
  onRestore: function (event, ownerInstance) {
    ownerInstance.callMethod('onRefresherRestore', event)
  },
  onAbort: function (event, ownerInstance) {
    ownerInstance.callMethod('onRefresherAbort', event)
  },
  onRefresh: function (event, ownerInstance) {
    var customRefresher = getCustomRefresher(ownerInstance)
    customRefresher.removeClass(refresherAfter, refresherBefore)
    ownerInstance.callMethod('onPullDownRefresh', event)
  },
}

2. 业务页面使用

<!-- pages/service/service.wxml -->
<view style="height: 500rpx;border: 1px solid red;">
  <custom-pull-down 
    class="custom-pull-down" 
    bind:onReachBottom="onReachBottom"
    bind:onPullDownRefreshEnd="onPullDownRefreshEnd"
  >
    <view slot="content" style="padding: 25rpx;">
      <view wx:for="{{ list }}" wx:key="name" class="item">
        <view>{{ item.name }}</view>
      </view>
    </view>
  </custom-pull-down>
</view>
// pages/service/service.js
Page({
  data: {
    list: [
      { name: 1 },
      { name: 2 },
      { name: 3 },
      { name: 4 },
      { name: 5 },
      { name: 6 },
      { name: 7 },
      { name: 8 },
    ]
  },
  onPullDownRefreshEnd(){
    console.log("下拉刷新...")
  },
  onReachBottom(){
    console.log("上拉加载...")
  }
})
// pages/service/service.json
{
  "usingComponents": {
    "custom-pull-down": "/components/customPullDown/index"
  }
}
/* pages/service/service.wxss */
.item {
  height: 80rpx;
  text-align: center;
  background-color: aquamarine;
  margin-bottom: 30rpx;![请添加图片描述](https://img-blog.csdnimg.cn/0672f383e2674c7e890fe66746b841b7.gif)

}

实现效果:
在这里插入图片描述

这里需要注意一般上拉加载会加载下一页,要考虑事件会重复触发,需要在请求里判断当前是否是请求中状态;还需要注意如果后端没有下一页了需要显示【没有更多数据了】的字眼。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

优小U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值