移动端使用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 // 从其他页面进入时不缓存
  }
})
相关推荐
极客小俊33 分钟前
粘性定位Position:sticky属性是不是真的没用?
前端
云端看世界36 分钟前
ECMAScript 类型转换 下
前端·javascript
云端看世界38 分钟前
ECMAScript 运算符怪谈 下
前端·javascript
云端看世界39 分钟前
ECMAScript 函数对象实例化
前端·javascript
前端爆冲40 分钟前
基于vue和flex实现页面可配置组件顺序
前端·javascript·vue.js
云端看世界41 分钟前
ECMAScript 中的特异对象
前端·javascript
il43 分钟前
Deepdive into Tanstack Query - 2.1 QueryClient 基础
前端
_十六1 小时前
看完就懂!用最简单的方式带你了解 TypeScript 编译器原理
前端·typescript
Komorebi_99991 小时前
Axios 是一个基于 Promise 的 HTTP 客户端,可用于浏览器和 Node.js 环境。以下是它的一些主要作用
javascript·ajax
云端看世界1 小时前
ECMAScript 运算符怪谈 上
前端·javascript·ecmascript 6