第三十六节: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

相关推荐
默_笙26 分钟前
🚥 给 RAG 装一台心电监护仪:LangSmith 全链路观测(上)
前端·javascript
前端snow1 小时前
ai agent --- mem0 外挂记忆系统
前端
特立独行的猫a2 小时前
用仓颉写一个 Tauri:IPC 的每次往返实现原理(web层到仓颉层的触发过程)
前端·ui·harmonyos·tauri·鸿蒙·仓颉
Dovis(誓平步青云)2 小时前
多个链接不等于多份证据,新闻核验看板怎样合并来源
java·服务器·前端·javascript·人工智能·pdf·电脑
骑着蜗牛撵大象3273 小时前
Qt 事件机制详解:从 QEvent 派生类到事件过滤器的全景指南
前端·python
qq_2518364573 小时前
理发管理系统 —— 会员模块
开发语言·前端·python·flask
Frag0ut3 小时前
2027 年浏览器展望:Chrome 与 Edge 的 AI 智能体进化方向
前端·人工智能·chrome·edge·浏览器·新功能
计算机魔术师4 小时前
从AI绘图鼻祖到音乐版权破局者,Stability AI如何被三大唱片巨头「收编」
前端
奕鼎竜瑆4 小时前
Chrome 插件开发实战指南:从入门到发布
前端·chrome
广州华水科技4 小时前
水库北斗GNSS变形监测系统及单北斗形变监测一体机应用解析
前端