移动端使用keep-alive将页面缓存和滚动缓存具体实现方法 - 详解

1. 配置组件名称

确保列表页组件设置了name选项,(组合式API额外配置):

TypeScript 复制代码
<!-- vue2写法 --> 
export default {
  name: 'UserList' // 必须与 <keep-alive> 的 include 匹配
}

<!-- vue3写法 --> 
defineOptions({
  name: "UserList"
});

2. 路由配置

在路由配置中添加 meta 标识是否需要缓存:

TypeScript 复制代码
{
    path: "/userList",
    name: "UserList",
    component: () => import("@/views/user/list.vue"),
    meta: {
      title: "用户列表",
      keepAlive: true // 自定义缓存标识
    }
  },

3. 动态缓存控制

在 App.vue 中使用 <keep-alive> 包裹路由视图,并动态判断缓存:

TypeScript 复制代码
<!-- 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 ) 处理返回时的逻辑:

TypeScript 复制代码
<div class="list_box" @scroll="handleScroll" ref="listRef"> 
    <van-list
        v-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. 高级场景:条件缓存

TypeScript 复制代码
// 在全局前置守卫中
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 // 从其他页面进入时不缓存
  }
})
相关推荐
军军君0110 小时前
Three.js基础功能学习五:雾与渲染目标
开发语言·前端·javascript·学习·3d·前端框架·three
程序员爱钓鱼10 小时前
Node.js 编程实战:RESTful API 设计
前端·后端·node.js
程序员爱钓鱼10 小时前
Node.js 编程实战:GraphQL 简介与实战
前端·后端·node.js
chilavert31810 小时前
技术演进中的开发沉思-284 计算机原理:二进制核心原理
javascript·ajax·计算机原理
罗技12310 小时前
Easysearch 集群监控实战(下):线程池、索引、查询、段合并性能指标详解
前端·javascript·算法
XiaoYu200211 小时前
第3章 Nest.js拦截器
前端·ai编程·nestjs
千寻girling11 小时前
面试官 : “ 说一下 Map 和 WeakMap 的区别 ? ”
前端·javascript·面试
2501_9240641111 小时前
2025年主流Web自动化测试工具功能与适用场景对比
前端·测试工具·自动化
可触的未来,发芽的智生11 小时前
一万个为什么:频率和相位
javascript·人工智能·python·程序人生·自然语言处理
IT_陈寒11 小时前
Vite 5 实战:7个鲜为人知的配置技巧让构建速度提升200%
前端·人工智能·后端