【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函数。

代码:

// 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();
		} 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,
	};
}

使用:

// setup
const {
    page,
    list,
    status,
    contentText,

    setList,
    handleReachBottom,
} = usePagination(getData);

async function getData() {
    console.log('getData success');
    const res = await getList({
        pageNum: page.value,
        pageSize: 10
    });
    setList(res);
}
// return...

// 监听底部,注意是小程序生命周期,不是methods里
onReachBottom() {
	this.handleReachBottom();
},

 完整列表页示例:

<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的选项式写法,而不能放到setup里。

把handleReachBottom等需要的变量和方法在setup里return暴露出来,然后setup以外的地方(如小程序生命周期,methods等)就可以用this访问到。

  • 20
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值