在使用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. UWP ListView嵌套ListView

    要求:加载全部的订单,每个订单里面有一个或者多个产品,在列表中要展现出来, 1. xaml界面 步骤:1.这里使用的是x:bind绑定所以要引入实体类命名空间(OrderList集合中类的命名空间): ...

  2. AspNetCore 小记

    1. Microsoft.AspNetCore.Hosting.IHostingEnvironment 的接口获取的值: WebRootPath:D:\参考资料\C#\AspNetCore开源项目\n ...

  3. Markdown 语法简体中文版

    Markdown 语法简体中文版(fork 于繁体中文版 http://markdown.tw/ ) http://wowubuntu.com/markdownhttps://github.com/r ...

  4. Dependency Injection 筆記 (1)

    <.NET 依賴注入>連載 (1) 本文从一个基本的问题开始,点出软件需求变动的常态,以说明为什么我们需要学习「依赖注入」(dependency injection:简称 DI)来改善设计 ...

  5. 关于 win32 下磁盘的遍历方法

    最近要写个在线专杀的东东,虽然是专杀(本来只要清除几个特定的文件和杀几个特定的进程,然后把用户的注册表恢复正常,很多病毒木马最喜欢干的一件事情就是写 映像劫持 然后机器一重启,安全相关的软件全部玩完了 ...

  6. 亿方云(用电话或者qq沟通是远远不够的,容易忘还不能反复催,最好的方式就是指定一个平台,团队内的人定期查看最新记录)

    作者:城年链接:http://www.zhihu.com/question/20579359/answer/106319200来源:知乎著作权归作者所有,转载请联系作者获得授权. 更新,文字发完后,好 ...

  7. Ruby元编程:执行某个目录下的全部测试用例

    目前手里有个测试项目各个feature的测试用例都放在对应的子目录下,虽然有自动化测试框架的帮助执行起来很方便,但是偶尔也有需要在本地执行某个feature的全部测试用例集合.因为本人对shell脚本 ...

  8. request的跳转

    使用request.getRequestDispather(url).forword(request,response)方法跳转页面 地址栏的路径不会发生改变,在后续的ajax调用 使用window. ...

  9. SYN012型B码时统

       SYN012型B码时统 产品概述 SYN012型B码时统是由西安同步电子科技有限公司精心设计.自行研发生产的一款通用性时统终端,内置高精度恒温晶振,接收GPS北斗双模卫星信号,10MHz外部参考 ...

  10. Liferay6.1 配置友好的URL映射

    说明:以下内容和官方文档相差不大,如果您英文较好,建议直接去读官方文档,地址是:https://dev.liferay.com/develop/tutorials/-/knowledge_base/6 ...