Vue3 零基础每日笔记(073):keep-alive 页面缓存实战——列表页返回不丢状态

一、前言

经典事故:列表页翻到第 5 页、筛了 3 个条件 → 点进详情 → 返回 → 全部重置回第 1 页。keep-alive(030 篇学过基础)就是解药,本篇讲企业级用法:按路由 meta 动态控制谁缓存,以及 onActivated 里"缓存后要不要刷新数据"的取舍。

二、keep-alive 缓存的本质

vue 复制代码
<router-view v-slot="{ Component }">
  <keep-alive :include="caches">
    <component :is="Component" />
  </keep-alive>
</router-view>

三个关键认知:

  1. 缓存的是组件实例:切走时组件不销毁(不触发 unmounted),切回来不重新创建------数据、滚动位置原样保留
  2. include 按组件名匹配 :值是组件的 name,不是路由 path!匹配不到就等于没缓存
  3. 配套生命周期 :被缓存的组件每次"回来"触发 onActivated、"离开"触发 onDeactivated(代替 onMounted 的重复触发)

三、组件名怎么来:script setup 用 defineOptions

include 匹配组件名,但 <script setup> 默认没有显式 name(隐式用文件名)。为了 include 不踩坑,给页面组件显式声明 name(Vue 3.3+ 内置宏):

vue 复制代码
<!-- src/views/GoodsListView.vue -->
<script setup lang="ts">
defineOptions({ name: 'GoodsList' })   // ★ 3.3+ 内置,无需插件
// ...其余代码
</script>

四、企业级方案:路由 meta + 动态 include

把"哪些页面要缓存"配置在路由 meta 里,Layout 里动态收集:

ts 复制代码
// src/router/index.ts
{
  path: '/',
  component: () => import('@/layout/Layout.vue'),
  children: [
    {
      path: 'goods/list',
      component: () => import('@/views/GoodsListView.vue'),
      meta: { title: '商品列表', keepAlive: true }   // ★ 要缓存的页面
    },
    {
      path: 'goods/detail/:id',
      component: () => import('@/views/GoodsDetailView.vue'),
      meta: { title: '商品详情' }                    // 不缓存
    }
  ]
}
vue 复制代码
<!-- src/layout/Layout.vue 的内容区替换为 -->
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'

const route = useRoute()
const router = useRouter()

// ★ 动态 include:只缓存 meta.keepAlive 的页面组件名
// 组件名与路由 name 约定一致,收集起来最省心
const caches = computed(() =>
  router.getRoutes()
    .filter((r) => r.meta?.keepAlive)
    .map((r) => r.name as string)
)
</script>

<template>
  <el-main>
    <router-view v-slot="{ Component }">
      <keep-alive :include="caches">
        <component :is="Component" />
      </keep-alive>
    </router-view>
  </el-main>
</template>

(路由对象加 name: 'GoodsList',与组件 defineOptions 的 name 一致。)

五、onActivated:缓存后要不要重新拉数据

缓存不是无脑"完全不动",典型策略:

vue 复制代码
<!-- src/views/GoodsListView.vue -->
<script setup lang="ts">
import { ref, onMounted, onActivated } from 'vue'

const keyword = ref('')
const list = ref([])

onMounted(() => {
  loadList()          // 首次进入:正常加载
})

onActivated(() => {
  // 从详情返回:默认啥都不做 → 状态原样保留(滚动位置、搜索、页码)
  // ★ 按需刷新场景:详情页可能改了数据,返回时要更新列表
  refreshIfDirty()
})

/** 详情页编辑后标记,回来重新拉数据 */
async function refreshIfDirty() {
  const edited = sessionStorage.getItem('goods-edited')
  if (edited) {
    sessionStorage.removeItem('goods-edited')
    await loadList()   // ★ 只刷新数据,不重置筛选和页码
  }
}

async function loadList() { /* 调接口,不影响 keyword/query */ }
</script>

决策表:

场景 onActivated 做什么
纯浏览(详情只是看) 什么都不做,完美还原现场
详情可能改数据 脏标记 → 只重拉数据,不动筛选/页码
需要每次都最新 不缓存该页(列表实时性 > 体验)

六、踩坑记录

  1. include 写了路由 path :include="['/goods/list']" 永远匹配不上------include 匹配组件 name
  2. script setup 组件没 name:隐式文件名在 Windows/大小写、路径变动时易出幺蛾子------页面组件一律 defineOptions 显式声明
  3. keep-alive 包错位置 :包在 router-view 外层但没接 v-slot 的写法不生效------必须 v-slot="{ Component }" + <component :is>
  4. 缓存页面太多内存暴涨 :每份缓存都是完整组件实例(含 DOM)------只缓存列表类页面,详情/表单页不缓存;再加 :max="10" 限上限(LRU 淘汰)
  5. onMounted 与 onActivated 双触发:首次进入 mounted 和 activated 都会触发,数据拉两遍------数据请求只放 onMounted,activated 里只做"按需刷新"
  6. 缓存了但期望每次进来自动刷新:这是需求矛盾不是 bug------要么不缓存,要么脏标记按需刷

七、今日小结

  • keep-alive 缓存组件实例:切走不销毁、回来不重建,现场完美还原
  • include 匹配 组件 name(defineOptions 显式声明),不是路由 path
  • 企业做法:路由 meta.keepAlive + Layout 动态收集 include
  • onActivated 策略:纯浏览不动 / 脏标记刷数据不动筛选 / 实时页不缓存

下篇预告

一页 1 万条数据渲染直接卡死浏览器?DOM 数量才是元凶。下一篇 074 长列表优化:手写一个虚拟列表搞懂原理,再用 vue-virtual-scroller 落地。

相关推荐
禾小西2 小时前
Redis:从两大维度和三大主线建立知识体系
数据库·redis·缓存
weixin_448119943 小时前
Datawhale Easy Data × AI:笔记1 已重做,看新的笔记
笔记
要开心吖ZSH4 小时前
MySQL 慢 SQL 排查操作手册-个人笔记版
java·笔记·sql·mysql·慢查询
咖啡忍者5 小时前
【SAP】程制造生产计划PP-PI(Production Planning for Process Industries)
笔记
Titan20246 小时前
MySQL索引学习笔记
笔记·学习·mysql
zhangrelay6 小时前
Arduino-MEGA-ESP单片机理论课笔记02-硬件-2026
笔记·单片机·嵌入式硬件
AOI小白新手上路6 小时前
VDMamba·AutoDL 复现笔记 · 学习笔记
笔记·学习
ACP广源盛139246256737 小时前
USB3.0 高速信号切换方案评估,LH3412 @ACP双通道差分开关硬件选型笔记
笔记·硬件架构·硬件工程·国产芯片·开关
自不量力的A同学8 小时前
Goldfish Scheme v18.11.39 发布了:迈向现代宏系统与多核并发
笔记