微信小程序官方没有给出具体的下拉刷新和上拉加载组件,我们可以基于小程序原生组件scroll-view的扩展与封装,实现简单的上拉加载、下拉刷新组件。
// 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": {}
}
<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)
},
}
<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;
}
这里需要注意一般上拉加载会加载下一页,要考虑事件会重复触发,需要在请求里判断当前是否是
请求中
状态;还需要注意如果后端没有下一页了需要显示【没有更多数据了】
的字眼。