微信小程序-上拉加载更多 下拉刷新组件
创建分页组件 pagination
- index.js
Component({
/**
* 组件的属性列表
*/
properties: {
// 传分页容器的样式, 如: "width: 100vw; height: 100vh;"
style: {
type: String,
value: "",
},
pageIndex: {
type: Number,
value: 0,
},
pageSize: {
type: Number,
value: 10,
},
},
/**
* 组件的初始数据
*/
data: {
triggered: false, // 下拉刷新中
isLoadMoreing: false, // 上拉加载中
isNoMore: false, // 是否没有更多数据
},
/**
* 组件的方法列表
*/
methods: {
// 下拉刷新
onPullDown(e) {
if (this._freshing) return;
this._freshing = true;
this.setData({
isNoMore: false,
pageIndex: 0,
});
this.triggerEvent("PullDown", {
pageIndex: this.data.pageIndex,
pageSize: this.data.pageSize,
callback: (res = []) => {
this.setData({
triggered: false,
pageIndex: res.length == 0 ? this.data.pageIndex : this.data.pageIndex + 1,
});
this._freshing = false;
},
});
},
// 上拉加载
onPullUp(e) {
if (this._loadMoreing || this.data.isNoMore) return;
this._loadMoreing = true;
this.setData({
isLoadMoreing: true,
pageIndex: this.data.pageIndex == 0 ? 1 : this.data.pageIndex,
});
this.triggerEvent("PullUp", {
pageIndex: this.data.pageIndex,
pageSize: this.data.pageSize,
callback: (res = []) => {
this.setData({
isLoadMoreing: false,
isNoMore: res.length == 0,
pageIndex: res.length == 0 ? this.data.pageIndex : this.data.pageIndex + 1,
});
this._loadMoreing = false;
},
});
},
},
});
- index.wxml
<scroll-view class="scroll" style="{{style}}" scroll-top="{{scrollTop}}" scroll-y="true" refresher-enabled="{{true}}" bindrefresherrefresh="onPullDown" refresher-triggered="{{triggered}}" lower-threshold="{{50}}" bindscrolltolower="onPullUp">
<!-- 列表区 -->
<slot></slot>
<!-- 上拉加载 -->
<view class="loadmore" hidden="{{!isLoadMoreing}}">
<view class="loadmore-icon"></view>
<view class="loadmore-tips">正在加载</view>
</view>
<!-- 我是底线 -->
<view wx:if="{{isNoMore}}" class="bot-line">我是有底线的</view>
</scroll-view>
- index.wxss
.scroll {
width: 100vw;
height: 100vh;
padding-bottom: 20rpx;
}
.loadmore {
width: 100%;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
}
.loadmore-tips {
vertical-align: middle;
}
.loadmore-icon {
margin: 0 5px;
width: 20px;
height: 20px;
vertical-align: middle;
-webkit-animation: weuiLoading 1s steps(12, end) infinite;
animation: weuiLoading 1s steps(12, end) infinite;
background: transparent
url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=)
no-repeat;
background-size: 100%;
}
.bot-line {
color: #333;
height: 100rpx;
line-height: 100rpx;
white-space: nowrap;
text-align: center;
}
.bot-line::before,
.bot-line::after {
content: "";
display: inline-block;
width: 24vw;
height: 1rpx;
background-color: #ddd;
vertical-align: super;
margin: 0 36rpx;
}
- index.json
{}
页面中使用
- index.wxml
<!-- index.wxml -->
<navigation-bar title="Weixin" back="{{false}}" color="black" background="#FFF"></navigation-bar>
<pagination class="scoll-view" style="width: 100vw;height: calc(100vh - 228rpx);" model:page-index="{{pageIndex}}" page-size="{{pageSize}}" bindPullDown="onPullDown" bindPullUp="onPullUp">
<view class="data-list" wx:for="{{list}}" wx:key="index">
<view class="data-item">{{index+1+" - "+item.name}}</view>
</view>
</pagination>
- index.js
// 模拟列表数据
const data = new Array(24).fill({
name: "大大大大大",
});
Page({
/**
* 页面的初始数据
*/
data: {
pageIndex: 0,
pageSize: 10,
list: [],
},
onLoad() {
this.getList();
},
// 下拉刷新
onPullDown(e) {
console.log("下拉刷新", e);
let callback = e.detail.callback;
this.getList()
.then(res => {
callback(res); // 成功回调
})
.catch(res => {
callback([]); // 请求失败也要执行回调关闭加载效果
});
},
// 上拉加载
onPullUp(e) {
console.log("上拉加载", e);
let callback = e.detail.callback;
this.getList()
.then(res => {
callback(res); // 成功回调
})
.catch(res => {
callback([]); // 请求失败也要执行回调关闭加载效果
});
},
getList() {
wx.showLoading({
title: "加载中...",
});
return new Promise((resolve, reject) => {
setTimeout(() => {
let { pageIndex, pageSize } = this.data;
let list = data.slice(pageIndex * pageSize, pageIndex * pageSize + pageSize);
this.setData({
list: pageIndex == 0 ? list : this.data.list.concat(list),
});
resolve(list);
wx.hideLoading();
}, 2000);
});
},
});
- index.json
{
"usingComponents": {
"navigation-bar": "/components/navigation-bar/navigation-bar",
"pagination": "../../components/pagination/index"
}
}
- index.wxss
/**index.wxss**/
page {
height: 100%;
}
.data-item {
margin: 20rpx;
background: #ccc;
height: 100rpx;
border-radius: 10rpx;
-webkit-border-radius: 10rpx;
-moz-border-radius: 10rpx;
-ms-border-radius: 10rpx;
-o-border-radius: 10rpx;
}