移动端使用keep-alive将页面缓存和滚动缓存具体实现方法 - 详解
1. 配置组件名称
确保列表页组件设置了name选项,(组合式API额外配置):
<!-- vue2写法 -->
export default {name: 'UserList' // 必须与 <keep-alive> 的 include 匹配
}<!-- vue3写法 -->
defineOptions({name: "UserList"
});
2. 路由配置
在路由配置中添加 meta 标识是否需要缓存:
{path: "/userList",name: "UserList",component: () => import("@/views/user/list.vue"),meta: {title: "用户列表",keepAlive: true // 自定义缓存标识}},
3. 动态缓存控制
在 App.vue 中使用 <keep-alive>
包裹路由视图,并动态判断缓存:
<!-- App.vue -->
<template><router-view v-slot="{ Component, route }"><keep-alive :include="cachedViews"><component:is="Component":key="route.fullPath"v-if="route.meta.keepAlive"/></keep-alive><component:is="Component":key="route.fullPath"v-if="!route.meta.keepAlive"/></router-view>
</template><script setup lang="ts">
import { ref, watch } from "vue";
import { useRoute } from "vue-router";const cachedViews = ref([]);
const route = useRoute();watch(() => route.meta.keepAlive,newVal => {if (newVal && !cachedViews.value.includes(route.name)) {cachedViews.value.push(route.name);}}
);
</script>
4. 生命周期钩子
在列表页组件中使用 activated 钩子(vue3 使用 onActivated ) 处理返回时的逻辑:
<div class="list_box" @scroll="handleScroll" ref="listRef"> <van-listv-model:loading="loading":finished="finished"finished-text="没有更多了"@load="getList">.......</van-list>
</div>const listRef = ref(null);
// 缓存分页和滚动位置
const cachedState = ref({page: 1,scrollTop: 0
});// 滚动事件处理
const handleScroll = e => {// 实时保存滚动位置cachedState.value.scrollTop = e.target.scrollTop;// console.log("cachedState.value.scrollTop", cachedState.value.scrollTop);
};onActivated(async () => {console.log("组件激活,执行激活时的操作", cachedState.value.page);if (cachedState.value.page > 1) {searchQuery.page = cachedState.value.page;}await nextTick();// 恢复滚动位置if (listRef.value) {listRef.value.scrollTop = cachedState.value.scrollTop;}
});onDeactivated(() => {// 保存当前状态cachedState.value.page = searchQuery.page;console.log("组件停用", cachedState.value.page);
});
6. 高级场景:条件缓存
// 在全局前置守卫中
router.beforeEach((to, from) => {if (from.name?.toString().includes('Detail') && to.name === 'UserList') {to.meta.keepAlive = true // 从详情页返回时缓存} else if (to.name === 'ListPage') {to.meta.keepAlive = false // 从其他页面进入时不缓存}
})