微信小程序组件:列表(上滑加载、回到顶部)
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文件中全局引用也可~