【uniapp】Vue3移动端滚动加载 分页组件的封装

今天用uniapp开发时想用vue3的组合式函数封装一个分页组件,如果是vue2自然就是用mixin了,因为组合式函数更灵活简洁,而且现在也写习惯了,还是决定封装一个vue3版的。

思路:

因为uniapp特有的对一些小程序生命周期的支持,比如onReachBottom可以直接监听页面到底,因此实现滚动加载其实很简单:

1.到页面底部给页数+1,同时判断是否正在加载中。

2.如果可以继续加载就推入list,然后通过接口返回的total和目前list长度判断后续是否还能继续加载。

3.搭配uni-load-more这个底部的加载样式组件,改变status和显示的文字contentText即可。

很坑的是,uniapp虽然说是支持vue3,文档里几乎没有vue3的示例代码,而且根据论坛里反馈的,对vue3.2的支持还不太好。我本来想尝试用vue3.2的script setup写法,却发现小程序的生命周期,像是分页时会用到的onReachBottom,根本没办法引入。最后只好用setup函数。

代码:

javascript 复制代码
// usePagination.js
import {
	reactive,
	toRefs
} from 'vue';

export default function usePagination(getData) {
	const state = reactive({
		status: 'more', // 可选值more loading noMore 和contentText的三个提示语相对应
		page: 1,
		total: 0,
		list: [],
		contentText: {
			contentdown: '查看更多',
			contentrefresh: '加载中',
			contentnomore: '没有更多了'
		},
		isLoadMore: false
	});

	async function handleReachBottom() {
		if (state.status === 'more' && !state.isLoadMore) {
			state.isLoadMore = true;
			state.page += 1;
			await handleLoadMore(getData);
			return true;
		}
	}

	async function handleLoadMore(func) {
		state.status = 'loading';
		console.log('handleLoadMore');
		try {
			const res = await func();
			setList(res)
		} catch (error) {
			console.error('Error during data loading:', error);
		}
	}

	function setList(res) {
		if (state.page === 1) {
			state.list = res.list;
		} else {
			state.list = state.list.concat(res.list);
		}
		state.total = res.total;
		setStatus()
	}

	function setStatus() {
		if (state.list.length === state.total) {
			state.contentText.contentdown = '没有更多了';
			state.status = 'noMore';
		} else {
			state.contentText.contentdown = '查看更多';
			state.status = 'more';
			state.isLoadMore = false;
		}
	}

	return {
		...toRefs(state),
		setList,
		handleReachBottom,
	};
}

使用:

javascript 复制代码
<template>
	<view class="page">
		<view class="content">
			<SearchComponent @search="handleSearch" />
			<ListComponent :list="list" />
			<uni-load-more :status="status" :content-text="contentText" />
		</view>
	</view>
</template>

<script>
	import {
		ref,
		reactive,
		onMounted
	} from 'vue';
	import SearchComponent from '../../components/SearchComponent';
	import ListComponent from './ListComponent';
	import usePagination from '../../../utils/usePagination.js';

	export default {
		components: {
			ListComponent,
			SearchComponent
		},
		setup() {
			const searchStr = ref('');
			const {
                page,
				list,
				status,
				contentText,

                setList,
				handleReachBottom,
			} = usePagination(getData);

			async function getData() {
			  console.log('getData success');
			  try {
				// 先模拟请求
			    const res = await new Promise(resolve => {
			      setTimeout(() => {
			        resolve({ list: [''], total: 1 });
			      }, 500);
			    });
			    setList(res);
			  } catch (error) {
			    console.error('error:', error);
			    throw error;
			  }
			}

			function handleSearch(val) {
				searchStr.value = val;
				getData();
			}

			onMounted(() => {
				// 第一次加载数据
				getData();
			});

			return {
				searchStr,
				handleSearch,
				// 分页
                page,
				list,
				status,
				contentText,
				handleReachBottom,
			};
		},
		onReachBottom() {
			this.handleReachBottom();
		}
	}
</script>

<style scoped lang="scss">
	.page {
		min-height: 100vh;
		background: #fff;
	}
</style>

可以看到onReachBottom这个生命周期目前只能用vue2的选项式写法,把handleReachBottom在setup里return暴露出来,然后生命周期,methods等方法里就可以用this访问到。

相关推荐
多客:duokelijie3 小时前
代练订单系统选型思路:跨品类游戏接入、订单分层管理、自动结算逻辑拆解!
数据库·mysql·微信小程序·前端框架·uni-app·php·持续部署
OpsEye5 小时前
大模型 Token 计量不准,是什么原因,怎么解决??
javascript·ai编程
独隅6 小时前
WebStorm Windows 版 React / Next.js 实战替换指南
javascript·windows·webstorm
冷眸_7 小时前
同名食材不能直接相减:一个 JavaScript 用量模型的边界
javascript
ruanno_top7 小时前
倒计时该用 deadline 还是每秒减一?我把两种写法都跑了一遍
vue.js
apollo_qwe7 小时前
接口超时了,前端为什么不能直接重试?
javascript·http
码间留白10 小时前
鸿蒙端对接 BLE 血压计:从一次握手到读数入库(二)设备篇
物联网·uni-app·鸿蒙·蓝牙ble·血压计
徐小夕11 小时前
下载量超 30 万的开源智能体 Prime Agent:它把自己从 TypeScript 重写成了 Rust
前端·vue.js·github
toooooop811 小时前
CRMEB 故障排查笔记:安全网关只放行 GET/POST 怎么办
前端·javascript·vue.js·thinkphp6·crmeb
软件技术NINI12 小时前
基于SpringBoot和Vue的项目评审系统
javascript·vue.js·spring boot·后端·spring·毕业设计·毕设