【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访问到。

相关推荐
搏博39 分钟前
在WPS中通过JavaScript宏(JSA)调用DeepSeek官网API优化文档教程
javascript·人工智能·windows·深度学习·机器学习·wps
BillKu1 小时前
el-input 中 select 方法使用报错:属性“select”在类型“HTMLElement”上不存在
前端·javascript·vue.js·elementui
涵信1 小时前
第一节:React 基础篇-React虚拟DOM原理及Diff算法优化策略
前端·javascript·react.js
碳烤小咸鱼2 小时前
蓝桥杯 Web 方向入门指南:从基础到实战
前端·javascript·css·蓝桥杯
inksci2 小时前
低代码控件开发平台:飞帆中粘贴富文本的控件
前端·javascript·低代码
不懂装懂的不懂2 小时前
【antd + vue】Tree 树形控件:默认展开所有树节点 、点击文字可以“选中/取消选中”节点
前端·javascript·vue.js
WEI_Gaot3 小时前
JS OBJECT 1 发展路线
前端·javascript
H5开发新纪元3 小时前
Vue3 + VantUI 多表单动态校验与提交最佳实践
前端·vue.js
Joet3 小时前
elementPlus_upload组件二次封装,cos上传
vue.js·typescript
饭团团团3 小时前
冷知识。🤔 何为 AMD 匿名模块冲突???
前端·javascript