微信小程序官方没有给出具体的下拉刷新和上拉加载组件,我们可以基于小程序原生组件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-viewrefresher-enabledscroll-yscroll-with-animationrefresher-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().thresholdvar isLargerThanTriggerThreshold = scrollY > thresholdcustomRefresher.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;}
实现效果:
这里需要注意一般上拉加载会加载下一页,要考虑事件会重复触发,需要在请求里判断当前是否是
请求中
状态;还需要注意如果后端没有下一页了需要显示【没有更多数据了】
的字眼。