列表页有一个上拉加载与下拉刷新的需求,这边用到了uniapp的<scroll-view></scroll-view>标签
官方文档:scroll-view | uni-app官网
根据文档,这次用到的有以下属性:
scroll-y:开启纵向滚动
refresher-enabled:开启自定义下拉刷新
refresher-triggered:设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
@scrolltolower:滚动到底部/右边时,会触发 scrolltolower 事件
@refresherrefresh:自定义下拉刷新被触发
refresher-default-style:设置自定义下拉刷新默认样式
这里有两个点需要注意:
- scroll-view标签一定要给高度,不然无效
- triggered的初始值为false,在下拉刷新触发时,要先变为true,在请求或者其它延时操作之后再将它变为false,才会有效果
<template>
<view>
<scroll-view
style="height: 100%"
:scroll-y="true"
:refresher-enabled="true"
:refresher-triggered="triggered"
@scrolltolower="scrolltolower"
@refresherrefresh="onRefresh"
refresher-default-style="black"
>
<!-- 需要滚动的区域 -->
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
triggered: false, // 下拉是否激活
tabDetailList: [],
total: 0,
pageNum: 1,
pageSize: 10,
};
},
methods: {
// 上拉加载
scrolltolower() {
if (this.tabDetailList.length < this.total) {
this.pageNum += 1;
// 继续请求下一页,记得保留原先数组
this.getTabCDetail();
} else {
uni.showToast({
title: "没有更多了",
icon: "none",
duration: 2000,
});
return;
}
},
// 自定义下拉刷新被触发
onRefresh() {
// 开启下拉自定义样式
this.triggered = true;
// 重新调用
this.init();
// 1秒之后复位
setTimeout((e) => {
this.triggered = false;
}, 1000);
},
},
};
</script>
<style lang="scss" scoped></style>
当时写完之后,碰到一个可能不算问题的问题
在自定义下拉刷新触发时,由于请求回来的很快,几乎在一瞬间就执行了this.triggered = false,在视觉上有个'一闪而过'的体验,觉得有点怪(我是将this.triggered的状态在请求中进行更改);后面经同事修改,他将this.triggered = false写在了setTimeout里面,这样样式有保留,数据也有更新
这里涉及到一个事件循环的知识点,我是这么理解的:
由于setTimeout与异步请求同属异步宏任务,代码从上往下执行,当 this.init() 被调用时,它会发起一个异步请求。该请求会被放入事件队列中,而不会立即执行,因为JavaScript是单线程的,它会等待事件循环处理这个请求。与此同时,setTimeout 也是一个异步操作,它会被放入事件队列中。在setTimeout中设置了1秒的延迟,因此它会在1秒后被执行。
由于事件队列是先进先出的,所以在事件循环中,this.init() 请求完成后,才会执行 setTimeout 中的操作。也就是说,不管this.init()请求回来得有多慢,setTimeout一定会在this.init()请求回来之后才会执行。