Vue2.0页面缓存机制联合页面标签的交互(keep-alive + router)

news2025/5/14 23:25:09

预期效果:(借助iview-ui的在线体验页面示意一下)

  1. 项目中只有一部分页面需要缓存,且存在多级路由的页面。
  2. 每打开一个菜单,就会新增一个 Tab标签,只要 Tab标签不关闭,对应的页面就会被缓存,Tab标签关闭时,页面才会被销毁。

在这里插入图片描述

以下是我自己琢磨出来的方案,可能有所欠缺,多多包涵,可以先翻到最后先大致了解一下相关逻辑。

代码实现

1. router.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '@/store'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('xxx/Login')
  },
  {
    path: '/myProfix', // 自定义的顶层路由前缀
    component: () => import('xxx/Main'),
    name: 'Main',
    redirect: { name: 'Home' },
    children: [
      {
	    path: 'home',
	    name: 'Home',
	    component: () => import('xxx/Home'),
	    meta: { keepAlive: true } // 需要缓存的页面路由在 meta中添加 keepAlive属性
	  },
	  {
	    path: 'about',
	    name: 'About',
	    component: () => import('xxx/About')
	  },
	  // 多级路由
	  {
	    path: 'father',
	    name: 'Father',
	    component: () => import('xxx/Father'),
	    redirect: { name: 'Son0' },
	    children: [
	      {
	        path: 'son0',
	        name: 'Son0',
	        component: () => import('xxx/Son0'),
	        meta: { keepAlive: true }
	      },
	      {
	        path: 'son1',
	        name: 'Son1',
	        component: () => import('xxx/Son1')
	      },
	    ]
	  }
    ]
  }
]

const router = new VueRouter({
  base: process.env.BASE_URL,
  routes
})

router.beforeEach((to, from, next) => {
  // 当前路由如支持缓存,将当前路由对应的页面组件名添加到 store中
  if (to.meta?.keepAlive) {
    // 支持多级路由,多级路由存顶级父级路由的组件名(这个顶级父路由是指顶层路由 /myProfix的下一级,示例中的路由 /myProfix下只有2 层,实际可以有 2层以上)
    store.dispatch('updateKeepAliveRouteComponents', { operation: 'add', value: to.matched[1]?.name || to.name })
  }
  next()
})

export default router

2. store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    keepAliveRouteComponents: [] // 需要缓存的路由对应的组件名称(此处组件名称与路由名称设置成一样,方便关闭 Tab标签时做匹配处理)
  },
  actions: {
    // 更新 keepAliveRouteComponents
    updateKeepAliveRouteComponents: ({ commit }, data) => {
      commit('UPDATE_KEEP_ALIVE_ROUTE_COMPONENTS', data)
    }
  },
  mutations: {
    // 关闭 Tab标签
    CLOSE_TAB (state, payload) {
      // ...此处省略关闭 Tab标签的逻辑
      // 删除 keepAliveRouteComponents中对应的组件名,以清除对应路由组件的缓存
      const curRouteName = ... // 根据实际情况获取到关闭 Tab标签对应的页面路由的 name
      this.commit('UPDATE_KEEP_ALIVE_ROUTE_COMPONENTS', { operation: 'delete', value: curRouteName })
    },
    // 更新 keepAliveRouteComponents
    UPDATE_KEEP_ALIVE_ROUTE_COMPONENTS (state, data) {
      const { operation, value } = data
      if (operation === 'add' && !state.keepAliveRouteComponents.includes(value)) {
        state.keepAliveRouteComponents.push(value)
      }
      if (operation === 'delete') {
        const valueIndex = state.keepAliveRouteComponents.indexOf(value)
        if (valueIndex !== -1) {
          state.keepAliveRouteComponents.splice(valueIndex, 1)
        }
      }
    },
    // 退出登录
    LOGOUT (state) {
      // ...
      // 清空 keepAliveRouteComponents,清除所有缓存的页面组件——其实也可以不清空,因为退出到 Login页面时, Main组件会被销毁
      state.keepAliveRouteComponents = []
    },
  }
})

3. App.vue

<template>
  <div id="app">
    <router-view />
  </div>
</template>

4. Main.vue

<template>
  <div class="main">
    <Navigation />
    <div class="main-view">
      // include属性与 store记录的 keepAliveRouteComponents绑定
      <keep-alive :include="keepAliveRouteComponents">
        <router-view />
      </keep-alive>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import Navigation from '@system/components/Navigation'

export default {
  components: {
    Navigation
  },
  computed: {
    ...mapState(['keepAliveRouteComponents']),
  }
}
</script>

5. Home.vue

<template>
  <div class="home"></div>
</template>

<script>
export default {
  name: 'Home'  // 组件名称与路由名称设置成一样
}
</script>

6. Father.vue

<template>
  <div class="father">
    <keep-alive :include="['Son0']">
      <router-view />
    </keep-alive>
  </div>
</template>

<script>
export default {
  name: 'Father' // 组件名称与路由名称设置成一样
}
</script>

7. Son0.vue

<template>
  <div class="son0"></div>
</template>

<script>
export default {
  name: 'Son0' // 组件名称与路由名称设置成一样
}
</script>

逻辑总结

  1. 需要缓存的页面路由添加meta属性{ keepAlive: true }
  2. 页面路由对应的组件名称与路由名称设置成一样,方便 Tab标签关闭时做匹配(这一步不是必须的,可以换成别的方法,只要 Tab标签关闭时,能有相关数据识别到对应的页面的组件名称即可)
  3. store中保存需要缓存的页面组件的名称列表keepAliveRouteComponents
  4. <Main>组件中 组件的include属性与keepAliveRouteComponents绑定
  5. 路由全局前置守卫中判断即将进入的路由keepAlive属性为true时,在keepAliveRouteComponents列表中加入当前路由的name,如果是多级路由即加入当前路由的顶级父级路由(/myProfix的下一级)的name(——可以统一通过$route.matched[1]来获取需要的name,为什么取matched[1],因为当前还有一层顶级的路由/myProfixmatched[0](此处记录路由的name,是基于将页面路由对应的组件名称与路由名称设置成一样的前提条件下)
  6. Tab标签关闭时,删除keepAliveRouteComponents中对应的组件名,以清除对应路由组件的缓存
  7. 多级路由的情况,内部子路由<router-view />包裹<keep-alive>,并根据具体子路由是否缓存添加include属性(——如果这个多级路由只有一个子路由,也可以不设置)
  8. 系统登出时,清空keepAliveRouteComponents(——其实清不清空无所谓,因为跳转到login页面时,整个<Main>组件都会被销毁)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333492.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java Jackson TypeReference获取泛型类型信息【泛型】

Jackson是一个比较流行的Json序列化和反序列化框架。本文以Jackson为例介绍TypeReference实现涉及泛型的反序列化&#xff0c;及TyperReference的实现原理。对于获取泛型类型信息的场景&#xff0c;TypeReference是一个可以参考的通用解决方案。 Jackson ObjectMapper的readVa…

三表相连 mapjoin

三表相连 mapjoin要求输出的样式三张表score.csvstudent.csvsubject.csv创建三个类StudentScgetset方法实现类MapJoinDriver用mapjoin不需要reduceMapJoinMapper运行结果要求 输出的样式 三张表 score.csv student.csv subject.csv 创建三个类 StudentSc getset方法 插入gets…

Mysql起步之环境搭建8.0

MySQL的下载、安装、配置 MySQL Community Server 社区版本&#xff0c;开源免费&#xff0c;自由下载&#xff0c;但不提供官方技术支持&#xff0c;适用于 大多数普通用户。 MySQL Enterprise Edition 企业版本&#xff0c;需付费&#xff0c;不能在线下载&#xff0c;可以试…

单元测试junit+mock

单元测试 是什么&#xff1f; 单元测试&#xff08;unit testing&#xff09;&#xff0c;是指对软件中的最小可测试单元进行检查和验证。至于“单元”的大小或范围&#xff0c;并没有一个明确的标准&#xff0c;“单元”可以是一个方法、类、功能模块或者子系统。 单元测试通…

Java中类是什么

类(class)是构造对象的模板或蓝图。 我们可以将类想象成制作小甜饼的模具&#xff0c;将对象想象为小甜饼。由类构造(construct)对象的过程称为创建类的实例(instance)。 正如前面所看到的&#xff0c;用Java 编写的所有代码都位于某个类里面。 标准 Java 库提供了几千个类&a…

【Axure教程】转盘抽奖原型模板

转盘抽奖是营销活动中很常用的一种方式&#xff0c;在线上我们也可以经常看到转盘抽奖的活动&#xff0c;所以今天作者就教大家在Axure中怎么制作一个转盘抽奖的原型模板。一、效果展示1、可以随机转动轮盘&#xff0c;轮盘停止时&#xff0c;指针对着的奖品高亮显示2、可以重复…

Qt + Clion + cmake 环境配置

本文不涉及QML&#xff0c;因为我没用过 用C写窗体&#xff0c;同时还有可视化UI界面&#xff0c;这不比控制台程序香吗&#xff1f;QAQ我大一写c大作业的时候要是知道这个东西&#xff0c;我绝对满分啊&#xff01;&#xff01;&#xff01;&#xff01; To&#xff1a; 新版…

Mysql—触发器

触发器 简介 触发器用于直接在某种操作后&#xff08;数据的增删改查等&#xff09;&#xff0c;通过事件执行设置触发器时的 sql 语句&#xff0c;具有原子性。 可通过 sql 语句直接编写&#xff0c;关键词&#xff1a;CREATE TRIGGER 触发器名称。 例如&#xff1a;在表 st…

String面试题

String面试题 总结的很好&#xff1a;https://blog.csdn.net/qq_45950109/article/details/116992408 String特点 1.被final关键字修饰&#xff0c;不能被继承。实现Serializable&#xff0c;表示支持序列化。实现Comparable&#xff0c;表示可以排序。 2.底层是char数组和…

2023上半年软考报名到弘博创新错不了

软考是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资格考试。 系统集成…

ChatGPT为什么这么火爆?这是一篇从入门到玩坏的教程

什么是ChatGPT ChatGPT是由OpenAI开发的一个人工智能聊天机器人程序&#xff0c;于2022年11月推出。该程序使用基于GPT-3.5架构的大型语言模型並通过强化学习进行训练。 ChatGPT可以做什么&#xff1f; 你能想到的&#xff0c;它基本上都能和你聊上两句&#xff0c;比如写一…

功率放大器的增益是什么意思

电子工程师在日常实验测试中经常会应用到功率放大器&#xff0c;在介绍功率放大器产品的时候经常会看到增益的参数指标。下面安泰电子就来为大家介绍功率放大器增益是什么意思。 一、功率放大器增益的定义&#xff1a; 功率放大器作为一种电子电路&#xff0c;可以通过获取外部…

TCP连接的状态详解以及故障排查(六)

TCP通信中服务器处理客户端意外断开 如果TCP连接被对方正常关闭&#xff0c;也就是说&#xff0c;对方是正确地调用了closesocket(s)或者shutdown(s)的话&#xff0c;那么上面的Recv或Send调用就能马上返回&#xff0c;并且报错。这是由于close socket(s)或者shutdown(s)有个正…

SQL盲注加速方法总结

sql盲注加速方法总结 盲注分为布尔盲注和时间盲注&#xff0c;一般为加快测试速度都用工具或者脚本跑。但有时还是很慢&#xff0c;这时就需要采取另外办法。在参考了一些资料后经过实验总结可行方案如下。1.二分法加速、2.与运算加速、3.二进制延时注入加速、4.dnslog OOB外带…

[Java 进阶面试题] HashTable, HashMap, ConcurrentHashMap 之间的区别

大家一切顺利~ 文章目录前言HashTable, HashMap, ConcurrentHashMap 之间的区别前言 本篇主要内容如标题 HashTable, HashMap, ConcurrentHashMap 之间的区别 1.ConcurrentHashMap最大优化之处是相比于HashTable,ConcurrentHashMap大大缩小了所冲突的范围,把一把大锁切成了多…

全球爆火的ChatGPT,能否推动芯片市场增长?

“我所热爱的是我真实的生活&#xff0c;因为它包含了我所有的经历和感受&#xff0c;是我每一天都在体验和思考的。”这句非常有诗意的话&#xff0c;来自最近爆火的ChatGPT。 ChatGPT作为一款智能机器人&#xff0c;上知天文下知地理&#xff0c;不仅能写文案&#xff0c;还…

在github上上传文件

一、new新建一个仓库 填写/勾选下面三个部分 二、右键本地的要上传的文件&#xff0c;选择”Git Bash Here"进入。 进入git界面&#xff1a; 三、依次输入下面的命令 1、生成readme文件。 echo "# 在这里填入readme里面的内容" >> README.md2、建立…

(深度学习快速入门)第五章第一节1:GAN概述

获取pdf&#xff1a;密码7281 一&#xff1a;什么是生成模型 生成模型&#xff1a;在概率统计理论中&#xff0c;生成模型是指能够随机生成观测数据的模型&#xff0c;尤其是在给定某些隐含参数的条件下。为了训练一个生成模型我们首先要收集在特定领域下的大量数据&#xff…

Java开发学习(四十八)----MyBatisPlus删除语句之逻辑删除

1、逻辑删除 接下来要讲解是删除中比较重要的一个操作&#xff0c;逻辑删除&#xff0c;先来分析下问题: 这是一个员工和其所签的合同表&#xff0c;关系是一个员工可以签多个合同&#xff0c;是一个一(员工)对多(合同)的表 员工ID为1的张业绩&#xff0c;总共签了三个合同&a…

蓝桥杯刷题022——发现环(拓扑排序、DFS/BFS)

2017国赛 题目描述 小明的实验室有 N 台电脑&#xff0c;编号1⋯N。原本这 N 台电脑之间有 N−1 条数据链接相连&#xff0c;恰好构成一个树形网络。在树形网络上&#xff0c;任意两台电脑之间有唯一的路径相连。 不过在最近一次维护网络时&#xff0c;管理员误操作使得某两台电…