移动端使用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 // 从其他页面进入时不缓存
  }
})
相关推荐
EndingCoder1 小时前
React从基础入门到高级实战:React 实战项目 - 项目三:实时聊天应用
前端·react.js·架构·前端框架
阿阳微客2 小时前
Steam 搬砖项目深度拆解:从抵触到真香的转型之路
前端·笔记·学习·游戏
德育处主任Pro2 小时前
『React』Fragment的用法及简写形式
前端·javascript·react.js
CodeBlossom3 小时前
javaweb -html -CSS
前端·javascript·html
CodeCraft Studio3 小时前
【案例分享】如何借助JS UI组件库DHTMLX Suite构建高效物联网IIoT平台
javascript·物联网·ui
打小就很皮...3 小时前
HBuilder 发行Android(apk包)全流程指南
前端·javascript·微信小程序
集成显卡4 小时前
PlayWright | 初识微软出品的 WEB 应用自动化测试框架
前端·chrome·测试工具·microsoft·自动化·edge浏览器
前端小趴菜055 小时前
React - 组件通信
前端·react.js·前端框架
Amy_cx5 小时前
在表单输入框按回车页面刷新的问题
前端·elementui
dancing9996 小时前
cocos3.X的oops框架oops-plugin-excel-to-json改进兼容多表单导出功能
前端·javascript·typescript·游戏程序