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>
相关推荐
Mintopia20 小时前
Vue3 项目如何迁移到 uni-app x:从纯 Web 到多端应用的系统指南
uni-app
Mintopia21 小时前
uni-app x 发展前景技术分析:跨端统一的新阶段?
uni-app
不爱说话郭德纲2 天前
告别漫长的HbuilderX云打包排队!uni-app x 安卓本地打包保姆级教程(附白屏、包体积过大排坑指南)
android·前端·uni-app
大米饭消灭者3 天前
Taro是怎么实现一码多端的【底层原理】
微信小程序·taro
HashTang3 天前
【AI 编程实战】第 12 篇:从 0 到 1 的回顾 - 项目总结与 AI 协作心得
前端·uni-app·ai编程
JunjunZ3 天前
uniapp 文件预览:从文件流到多格式预览的完整实现
前端·uni-app
郑州光合科技余经理4 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
TT_Close4 天前
“啪啪啪”三下键盘,极速拉起你的 uni-app 项目!
vue.js·uni-app·前端工程化
FliPPeDround4 天前
Vitest Environment UniApp:让 uni-app E2E 测试变得前所未有的简单
微信小程序·e2e·前端工程化
FliPPeDround4 天前
微信小程序自动化的 AI 新时代:wechat-devtools-mcp 智能方案
微信小程序·ai编程·mcp