第三十六节:keep-alive 页面缓存(Vue3 + 后台管理系统)

第三十六节:keep-alive 页面缓存(Vue3 + 后台管理系统)

本节目标:

实现路由页面缓存 ,切换标签页回来保留表单 / 表格查询条件、页码;离开页面不销毁组件;不需要缓存的页面可以排除。

对应咱们项目的 TagsView 标签页,就是搭配 keep-alive 使用,属于当前主线内容,现在直接讲。

原理

keep-alive 是 Vue 内置组件,缓存组件实例,不会销毁。

  • 打开页面:onMounted 只执行一次
  • 切走再切回来:不会重新请求接口,直接复用之前 DOM 和数据
  • 生命周期:onActivated(激活,每次进入) / onDeactivated(失活,切走)

步骤 1:修改布局 src/layout/index.vue

复制代码
<template>
  <div class="layout-container">
    <Sidebar />
    <div class="main-container">
      <AppHeader />
      <TagsView />
      <!-- 核心:keep-alive + router-view -->
      <router-view v-slot="{ Component }">
        <keep-alive :include="cachedViews">
          <component :is="Component" />
        </keep-alive>
      </router-view>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useTagsViewStore } from '@/stores/tagsView'
const tagsViewStore = useTagsViewStore()
// 从pinia取出需要缓存的页面名称数组
const cachedViews = ref(tagsViewStore.cachedViews)
</script>

步骤 2:改造 src/stores/tagsView.js

新增 cachedViews 数组,用来存放组件 name ,keep-alive 的 include 靠组件 name 匹配缓存!

⚠️重点坑:keep-alive 匹配的是组件选项 name,不是路由 path!

复制代码
import { defineStore } from 'pinia'
export const useTagsViewStore = defineStore('tagsView', {
  state: () => ({
    visitedViews: [], // 标签页列表(展示用)
    cachedViews: []   // keep-alive缓存名称数组
  }),
  actions: {
    // 添加标签,同时加入缓存
    addView(view) {
      if (this.visitedViews.some(v => v.path === view.path)) return
      this.visitedViews.push({
        path: view.path,
        title: view.meta?.title || 'no-name'
      })
      // 有组件name,才加入缓存
      if (view.name && !this.cachedViews.includes(view.name)) {
        this.cachedViews.push(view.name)
      }
    },
    // 删除标签,同时移除缓存
    delView(view) {
      const index = this.visitedViews.findIndex(v => v.path === view.path)
      if (index > -1) {
        this.visitedViews.splice(index, 1)
      }
      // 删除缓存名称
      if (view.name) {
        const cacheIndex = this.cachedViews.indexOf(view.name)
        if (cacheIndex > -1) {
          this.cachedViews.splice(cacheIndex, 1)
        }
      }
      // 返回剩下的标签用于页面跳转
      return this.visitedViews[this.visitedViews.length - 1]
    },
    // 关闭其他标签
    delOthersViews(view) {
      this.visitedViews = this.visitedViews.filter(item => {
        return item.path === view.path || item.path === '/dashboard/index'
      })
      this.cachedViews = this.cachedViews.filter(name => {
        return view.name === name || name === 'Dashboard'
      })
    },
    // 关闭全部
    delAllViews() {
      const dashboard = this.visitedViews.find(v => v.path === '/dashboard/index')
      this.visitedViews = dashboard ? [dashboard] : []
      this.cachedViews = dashboard ? ['Dashboard'] : []
    }
  }
})

步骤 3:给业务页面添加 name 属性(必须!)

示例 src/views/system/user/index.vue

复制代码
<script setup>
// ✅ 定义组件name,keep-alive靠这个识别
defineOptions({
  name: 'UserList'
})
// 剩下你的页面逻辑...
</script>

工作台页面 dashboard/index.vue

复制代码
<script setup>
defineOptions({
  name: 'Dashboard'
})
</script>

步骤 4:生命周期变化(缓存页面要用)

复制代码
// 首次进入执行一次
onMounted(() => {
  console.log('组件挂载')
})
// ✅ 每次切换标签回来都会执行(缓存页面推荐在这里请求数据)
onActivated(() => {
  console.log('页面激活')
  // getList()
})
// ✅ 页面切走失活
onDeactivated(() => {
  console.log('页面缓存,暂时隐藏')
})

测试清单

  1. 重启项目,进入用户管理页面,设置查询条件、页码
  2. 切到别的标签,再切回用户管理
    ✅ 查询条件、页码保留,不会重新刷新页面
  3. 关闭标签,cachedViews 自动移除组件 name,再次打开页面会重新加载
  4. 关闭其他标签、关闭全部,缓存数组同步清理

常见坑

  1. ❗忘记写 defineOptions({name:'xxx'}) → keep-alive 不生效

  2. 动态路由路由对象里要把路由的 name 带上,mock 路由补充 name 字段

    {
    path: '/system',
    component: 'Layout',
    name: 'System',
    meta: { title: '系统管理', icon: 'Setting' },
    children: [
    {
    path: 'user/list',
    component: 'system/user/index',
    name: 'UserList',
    meta: { title: '用户列表', icon: 'User' }
    }
    ]
    }

  3. 如果不需要缓存某个页面:不写组件 name 即可,不会进入 cachedViews

相关推荐
m0_敲代码的彭于晏1685 小时前
Vercel 前端部署平台深度评测
前端
2301_32241428045 小时前
基于SpringBoot+Vue的休闲零食超市管理系统的设计与实现59004-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·redis·mysql·决策树·推荐算法
怕浪猫7 小时前
外包和大厂的前端代码,差在凌晨三点
前端·面试·github
m0_敲代码的彭于晏1687 小时前
Vercel 前端部署与全栈开发实战指南
前端·状态模式
徐小夕7 小时前
花了3个月,我们做了一款 AI 版的“飞书文档”
前端·算法·github
贾伟康7 小时前
【化学实验室|17】HarmonyOS ArkTS 亮暗色与视觉令牌实战:集中颜色、间距和交互状态避免页面割裂
前端·移动开发·harmonyos·arkts·arkui
Csvn8 小时前
SSR/SSG/ISR(上):峡谷与渲染策略的时间预算
前端
Csvn8 小时前
SSR/SSG/ISR(下):可交互性、新鲜度与回源账
前端
microrain9 小时前
SagooIoT 的缓存换后端只改一行配置,文件后端连 Redis 都不需要
物联网·缓存·golang·sagooiot
Elcker11 小时前
YnuoAgent(依诺):一个 npm 包,跑起属于自己的 AI 研发平台
前端·人工智能·npm