在使用Vue开发管理系统项目的时候,为了保存页面的浏览状态,我们可以使用内置组件keep-alive来缓存组件内部状态,避免重新渲染。

<keep-alive>
<router-view></router-view>
</keep-alive>

  被keep-alive包裹的动态组件或router-view会缓存不活动的实例,再次被调用这些被缓存的实例会被再次复用,而不需要再次发送HTTP请求。对于使用tabs标签页打开页面时,这正是我们想要的效果。但是这样做同时也存在一个问题,就是被keep-alive包裹的组件会保持最后一次请求数据的渲染结果,即使我们关闭了tabs页,再次打开时依旧是上一次的状态。这时,我们就得用上include、exclude属性来对缓存的组件进行筛选。

Props:

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive> <!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive> <!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>

有了include和exclude对组件进行筛选,然后动态的记录tabs中打开的组件名,这就完美的解决了动态缓存的问题。所以在配置路由文件时,我们必须得先import组件,然后以组件名调用。

import HelloWorld from '@/components/HelloWorld'
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}

但是,在项目开发中,为了提升页面加载的速度,一般会采用路由懒加载的方式加载路由组件,这时调用的组件不再是通过组件名,而是匿名组件。

{
path: '/home',
name: 'home',
component: resolve => require(['@/components/learn/home'], resolve)
}

可是,官方文档指出:

匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配。

这样一来include和exclude就无效了。。。

额(⊙o⊙)…目前我们项目就是这样通过匿名组件调用的,所以就没有使用keep-alive组件。这时领导试用系统,咦...我这打开的页面怎么每次点进去都重置了页面内容,怎么不能像打开网页那样,我看到哪就给保存那时的状态呢,不过由于大家说弄不了,就把这个功能推掉了。

但是这段时间正好手中的事告一段落了,有空余时间,并本着有问题就得解决的原则,就自己琢磨起来。首先使用keep-alive进行全站缓存这个是肯定不行的,使用者肯定得说:怎么我把页面关了打开后还是之前的呢。。。所以,感觉这是一个很复杂的问题,要不然早就加上了。

于是乎,打开度娘寻找心灵安慰。找吖找吖找,也不知在清一色的复制粘帖中摸索了多久,除了使用include来解决动态缓存问题,完全没有对匿名组件的解决方案。就在快要放弃和度娘交流时,突然眼前闪过一丝希望的光芒!

终于发现了大神研究出的可行方案:Vue 全站缓存之 keep-alive : 动态移除缓存   https://juejin.im/post/5b610da4e51d45195c07720d

在茫茫代码中,他一眼就看到了隐藏在角落里的vue-component-12-keep-alive,然后才有了完美的解决方案。那就是使用Vue.mixin的方法拦截了路由离开事件,并在该拦截方法中实现了销毁页面缓存的功能。

// 全局混入,关闭tab时清除组件缓存
Vue.mixin({
beforeRouteLeave(to, from, next) {
let flag = true
this.$store.state.options.forEach(e => { // options存储打开的tabs的组件路由
if(from.path == e.route) {
flag = false
}
})
if(flag && this.$vnode.parent && this.$vnode.parent.componentInstance.cache) {
let key = this.$vnode.key // 当前关闭的组件名
let cache = this.$vnode.parent.componentInstance.cache // 缓存的组件
let keys = this.$vnode.parent.componentInstance.keys // 缓存的组件名
if(cache[key] != null) {
delete cache[key]
let index = keys.indexOf(key)
if(index > -1) {
keys.splice(index, 1)
}
}
}
next()
}
})

不过在这之前我们还得解决一个问题,由于此方法是拦截了路由离开事件,而当我们关闭不是当前激活的标签页时是不会触发路由离开事件的,这就会导致清除该缓存失效,所以我们得在关闭不激活的标签页时先模拟一次点击事件才能达到预期的效果。

    // 移除tab标签
tabRemove (targetName) {
let event = new Event('click')
document.getElementById("tab-" + targetName).dispatchEvent(event) // 触发点击事件 this.$store.commit('delete_tabs', targetName);
if (this.activeIndex === targetName) {
// 设置当前激活的路由
if (this.openTab && this.openTab.length >= 1) {
this.$store.commit('set_active_index', this.openTab[this.openTab.length - 1].route);
this.$router.push({ path: this.activeIndex });
} else {
this.$router.push({ path: '/' });
}
}
}

OK,这样就完美了解决了匿名组件动态清除缓存的问题了。

Vue匿名组件使用keep-alive后动态清除缓存的更多相关文章

  1. Vue UI组件 开发框架 服务端 辅助工具 应用实例 Demo示例

    Vue UI组件 开发框架 服务端 辅助工具 应用实例 Demo示例 element ★11612 - 饿了么出品的Vue2的web UI工具套件 Vux ★7503 - 基于Vue和WeUI的组件库 ...

  2. Vue父组件向子组件传递一个动态的值,子组件如何保持实时更新实时更新?

    原文:https://blog.csdn.net/zhouweixue_vivi/article/details/78550738 2017年11月16日 14:22:50 zhouweixue_vi ...

  3. vue教程3-03 vue组件,定义全局、局部组件,配合模板,动态组件

    vue教程3-03 vue组件,定义全局.局部组件,配合模板,动态组件 一.定义一个组件 定义一个组件: 1. 全局组件 var Aaa=Vue.extend({ template:'<h3&g ...

  4. vue父组件向子组件动态传值的两种方法

    在一些项目需求中需要父组件向子组件动态传值,比如我这里的需求是,父组件动态通过axios获取返回的图片url数组然后传给子组件,上传图片的子组件拿到该数组后进行遍历并展示图片,因为有时候获取到的会是空 ...

  5. c# 把一个匿名对象赋值给一个Object类型的变量后,怎么取这个变量? c# dynamic动态类型和匿名类 详解C# 匿名对象(匿名类型)、var、动态类型 dynamic 深入浅析C#中的var和dynamic

    比如有一个匿名对象,var  result =......Select( a=>new {  id=a.id, name=a.name});然后Object  obj =  result ;我怎 ...

  6. [vue]子组件通过props获取父组件数据以及使用watch解决动态数据不生效问题

    父子组件的传值,在Vue官方也写得很清楚,父组件中使用v-bind绑定传送,子组件使用props接收. 父组件通过v-bind绑定数据: <template> <router-vie ...

  7. Vue(七) 组件详解

    组件 (Component) 是 Vue.js 最核心的功能,也是整个框架设计最精彩的部分,当然也是最难掌握的. 组件与复用 组件用法 组件与创建 Vue 实例类似,需要注册后才可以使用.注册有全局注 ...

  8. vue.js组件化开发实践

    前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎么实现,技术选型自然 ...

  9. VUE.JS组件化

    VUE.JS组件化 前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎 ...

随机推荐

  1. EF Power Tool 代码生成器 反向生成

    大致来说,这个工具有这样几个功能: 1) 按照现有数据库结构,生成Code First POCO class.DbContext class和相应的mapping class. 2) 以designe ...

  2. Django预备知识

    http协议 url: 协议://域名(IP)+端口(80)/路径?参数(a=1&b=2) 示例:https://www.baidu.com/s/?wd=aaa MVC M:mdoel 与数据 ...

  3. 第一个SpringBoot测试实例

    1.SpringBoot项目构建:http://start-spring.io   自动化构建SpringBoot项目,保存在本地并解压 2.安装gradle并配置gradle环境 3.配置阿里云ma ...

  4. .NET开发框架(一)-框架介绍与视频演示

    本文主要介绍一套基于.NET CORE的SPA高并发.高可用的开发框架. 我们暂且称它为:(让你懂.NET)开发框架. 以此为主线,陆续编写教程,讲述如何构建高并发.高可用的框架. (欢迎转载与分享) ...

  5. web页面的时间传入servlet如何转换为可以存入MySQL的Date类型

    在web页面中当使用如下语句: <input type="date" name="startTime"/> 提交到servlet中 在servlet ...

  6. Spring Boot:使用Redis存储技术

    综合概述 Redis是一个开源免费的高性能key-value数据库,读取速度达110000次/s,写入速度达81000次/s.Redis支持丰富的数据类型,如Lists, Hashes, Sets 及 ...

  7. 《Spring Cloud》学习(三) 容错保护!

    在微服务架构中,我们将系统拆分成了很多服务单元,各单元的应用间互相依赖.由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身间题出现调用故障或延迟,而 ...

  8. 基于maven的项目脚手架,一键创建项目的项目模板

    制作基于maven的项目脚手架 Springboot的出现极大的简化了项目开发的配置,然而,到真实使用的时候还是会有一堆配置需要设定.比如依赖管理,各种插件,质量扫描配置,docker配置,持续集成配 ...

  9. C语言之父Dennis Ritchie告诉你:如何成为世界上最好的程序员?

    文/Ohans Emmanuel 译/网易云信 想要阅读更多技术干货文章,欢迎关注网易云信博客. 了解网易云信,来自网易核心架构的通信与视频云服务. 我不知道如何成为世界上最好的程序员.但是,我们可以 ...

  10. HBase 学习之路(八)——HBase协处理器

    一.简述 在使用HBase时,如果你的数据量达到了数十亿行或数百万列,此时能否在查询中返回大量数据将受制于网络的带宽,即便网络状况允许,但是客户端的计算处理也未必能够满足要求.在这种情况下,协处理器( ...