uniapp微信小程序商品列表数据分页+本地缓存+下拉刷新+图片懒加载

图片懒加载写在scroll-view标签下的image里

html 复制代码
	<image lazy-load :src="car.mainImageUrl ?car.mainImageUrl :'/static/logo.jpg'" mode="aspectFill"
					class="car-item-image"></image>

完整代码

html 复制代码
<template>
		<scroll-view scroll-y @scrolltolower="loadMore" refresher-enabled @refresherrefresh="onPullDownRefresh">
			<carlist :view-mode="viewMode" :carList="carList" />
		</scroll-view>
	</view>
</template>
<script setup>
	import {
		onMounted,
		ref
	} from 'vue';

	import {
		onPullDownRefresh,
		onPageShow,
		onShareAppMessage,
		onShareTimeline
	} from '@dcloudio/uni-app'
	import {
		t
	} from '@/utils/i18n'
	import api from '@/utils/api.js'

	// --- 响应式数据 ---
	const carList = ref([]);
	const pageNum = ref(1); // 当前页码
	const pageSize = 10; // 每页数量,与后端接口保持一致
	const hasMore = ref(true); // 是否还有更多数据
	const loadingMore = ref(false); // 是否正在加载更多
	const isRefreshing = ref(false); // 是否正在下拉刷新

	// --- 本地缓存的 key ---
	const CACHE_KEY = 'carListCache';
	const CACHE_TIME_KEY = 'carListCacheTime';
	const CACHE_EXPIRY = 30 * 60 * 1000; // 缓存有效期,30分钟

	/**
	 * 获取车辆列表数据
	 * @param {boolean} isRefresh - 是否为下拉刷新
	 */
	const getCarList = async (isRefresh = false) => {
		// 如果正在加载更多或没有更多数据,则直接返回
		if (loadingMore.value || !hasMore.value && !isRefresh) {
			return;
		}

		if (isRefresh) {
			isRefreshing.value = true;
			pageNum.value = 1; // 刷新时重置页码
			hasMore.value = true;
		}

		loadingMore.value = true;
		try {
			const result = await api.car.getList({
				pageNum: pageNum.value,
				pageSize
			});

			const records = result.data.records || [];
			// 检查是否有数据,如果后端返回的数据条数少于 pageSize,则表示没有更多数据了
			if (records.length < pageSize) {
				hasMore.value = false;
			}
			
			// 下拉刷新时,清空原有列表
			if (isRefresh) {
				carList.value = records.reverse();
				// 刷新成功后更新缓存
				uni.setStorageSync(CACHE_KEY, carList.value);
				uni.setStorageSync(CACHE_TIME_KEY, Date.now());
			} else {
				// 上拉加载时,追加新数据
				carList.value = [...carList.value, ...records.reverse()];
			}

			pageNum.value++; // 页码递增
		} catch (error) {
			console.error('获取列表失败:', error);
			// 接口报错时,将hasMore设为false以避免无限加载
			hasMore.value = false; 
			// 提示用户加载失败
			uni.showToast({
				title: t('common.load_failed'),
				icon: 'error',
				duration: 2000
			});
		} finally {
			loadingMore.value = false;
			isRefreshing.value = false;
			uni.stopPullDownRefresh(); // 关闭下拉刷新动画
		}
	}

	// 监听小程序生命周期
	onPageShow(() => {
		const cachedData = uni.getStorageSync(CACHE_KEY);
		const cacheTime = uni.getStorageSync(CACHE_TIME_KEY);

		// 如果有缓存且未过期,使用缓存数据
		if (cachedData && cacheTime && (Date.now() - cacheTime < CACHE_EXPIRY)) {
			carList.value = cachedData;
			console.log('使用本地缓存数据');
		} else {
			// 没有缓存或缓存过期,加载最新数据
			console.log('缓存失效或无缓存,加载最新数据');
			getCarList(true); // 首次加载使用刷新模式
		}
	});
	
	/**
	 * 上拉加载更多
	 */
	const loadMore = () => {
		if (hasMore.value && !loadingMore.value) {
			console.log("加载更多");
			getCarList();
		} else {
			console.log("没有更多数据或正在加载");
		}
	};
	
	/**
	 * 页面级下拉刷新
	 */
	const onPullDownRefresh = () => {
		console.log("触发下拉刷新");
		getCarList(true);
	};

</script>
相关推荐
Java永无止境38 分钟前
延时任务之Redis 过期事件监听原理与缺陷
数据库·redis·缓存·延时任务
java1234_小锋1 小时前
Redis线上操作最佳实践有哪些?
数据库·redis·缓存
2501_915918413 小时前
Video over HTTPS,视频流(HLSDASH)在 HTTPS 下的调试与抓包实战
网络协议·http·ios·小程序·https·uni-app·iphone
鱼樱前端5 小时前
uni-app快速入门章法(一)
前端·uni-app
麦兜*6 小时前
Redis多租户资源隔离方案:基于ACL的权限控制与管理
java·javascript·spring boot·redis·python·spring·缓存
gsfl6 小时前
Redis 数据库管理与通信基础
数据库·redis·缓存
Q_Q5110082856 小时前
python+springboot+uniapp基于微信小程序的任务打卡系统
spring boot·python·django·flask·uni-app·node.js·php
李慕婉学姐6 小时前
【开题答辩过程】以《基于SpringBoot+Vue+uni-app的智慧校园服务系统的设计与实现》为例,不会开题答辩的可以进来看看
spring boot·uni-app
withoutfear6 小时前
uni-app 开发H5软键盘会顶起底部内容的解决方案
uni-app·软键盘
小咕聊编程6 小时前
【含文档+PPT+源码】基于微信小程序的房屋租赁系统
微信小程序·小程序·房屋租赁