订单、消息、资讯类列表都要做分页。UniApp 页面自带 onReachBottom 生命周期,不必手动监听滚动;只要把页码、列表、是否还有下一页等状态收敛成组合式函数,任意列表页都能复用同一套逻辑。
实现思路
维护 page 与 hasMore 两个状态:加载成功后若返回条数小于 pageSize 则认为没有下一页;onReachBottom 里判断加载中或没有更多直接 return,否则 page 加一再请求;下拉刷新时把 page 重置为 1 并清空列表。
封装组合式函数
// composables/usePagedList.js
import { ref } from "vue";
export function usePagedList(apiFn, pageSize = 10) {
const list = ref([]);
const page = ref(1);
const loading = ref(false);
const finished = ref(false);
const refreshing = ref(false);
async function load(append = true) {
if (loading.value || finished.value) return;
loading.value = true;
try {
const data = await apiFn(page.value, pageSize);
const records = data.records || data.list || [];
list.value = append ? [...list.value, ...records] : records;
if (records.length < pageSize) finished.value = true;
} finally {
loading.value = false;
refreshing.value = false;
}
}
function refresh() {
page.value = 1;
finished.value = false;
return load(false);
}
function next() {
page.value += 1;
return load(true);
}
return { list, loading, finished, refreshing, refresh, next };
}
页面接入
// pages/news/list.vue
import { http } from "/utils/request";
import { usePagedList } from "/composables/usePagedList";
const { list, loading, finished, refreshing, refresh, next } = usePagedList(
(page, size) => http.get("/news/list", { page, size }),
15
);
// 生命周期钩子
onLoad(() => refresh());
onReachBottom(() => next());
onPullDownRefresh(() => {
refresh().finally(() => uni.stopPullDownRefresh());
});
模板状态渲染
底部用统一判断渲染三种状态:加载中、没有更多、空数据,页面无需各自重复写。
<template>
<view v-for="item in list" :key="item.id" class="news-item">
{{ item.title }}
</view>
<view v-if="loading" class="list-footer">加载中...</view>
<view v-else-if="finished && list.length" class="list-footer">没有更多了</view>
<view v-else-if="finished && !list.length" class="list-empty">暂无数据</view>
<button v-if="error" @click="refresh">加载失败,点击重试</button>
</template>
pages.json 配置
下拉刷新需在 pages.json 对应页面开启 enablePullDownRefresh,并把列表页 style 中的开关置为 true。
需要注意
- onReachBottom 只在整页滚动时触发,若列表包在 scroll-view 内需改用 scrolltolower 事件;
- 防重复:触底事件可能连续触发多次,loading 判断必须放在函数最前;
- 切换 Tab 或条件筛选变化时先调用 refresh,避免残留上一条件的数据;
- 后端接口分页参数命名不一时,在 apiFn 里做一次适配即可,不影响复用。
小结
把分页逻辑收进组合式函数后,新列表页只需要传接口函数并渲染 list,上拉、下拉、空态全部现成,能大幅减少重复样板代码。
评论(0)
暂无评论,快来抢沙发吧~