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>
相关推荐
结网的兔子3 分钟前
【前端开发】UniApp 项目地图选型与Web-APP跨端迁移方案
前端·uni-app
名字还没想好☜34 分钟前
Java 用 MethodHandle 替代反射:调用性能实测、invokeExact 的坑与缓存
java·开发语言·缓存·反射·methodhandle
acd1200942 分钟前
Redis 缓存和数据库一致性,到底怎么搞?
数据库·redis·缓存
小当家.10544 分钟前
LLM服务缓存与连接池管理:三层缓存架构与ChatClient池化
java·后端·spring·缓存·llm·agent
CodeBlog-star1 小时前
AI Agent 高并发实战:Redis 限流、队列、缓存与高可用全栈方案
数据库·redis·缓存
小当家.1051 小时前
Token成本控制实战:语义缓存、上下文压缩与工具缓存
java·spring·缓存·token·上下文
java1234_小锋13 小时前
【免费】基于Python的微信小程序网约车(打车,在线叫车,移动出行)系统(FastAPI+Vue3) 锋哥原创出品,必属精品
微信小程序·小程序·fastapi·网约车系统·在线叫车系统
thesky12345615 小时前
智能体面试准备(二十六):Agent 成本工程——模型路由、缓存、预算控制与大小模型分工
缓存·llmops·智能体·模型路由·成本工程·预算控制·小模型分工
2501_9160074718 小时前
Bundle ID 注册与管理 App ID 创建指南 命名规则 权限开关与删除注意事项
android·ios·小程序·https·uni-app·iphone·webview
cfm_291419 小时前
高并发系统缓存全解
java·缓存