vue中如何使用keep-alive动态删除已缓存组件(keep-alive,vue,开发技术)

时间:2024-05-03 08:11:58 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

本文小编为大家详细介绍“vue中如何使用keep-alive动态删除已缓存组件”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue中如何使用keep-alive动态删除已缓存组件”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

项目场景

在做后台管理系统的时候,有这样一个需求:

后台的界面如下:

vue中如何使用keep-alive动态删除已缓存组件

点击左边的菜单,会在右边的顶部生成一个个tag导航标签。当打开多个tag页时,用户可以在多个tag之间进行切换。需要在新增,修改页面切换tag时候,保留之前的信息,不进行页面的刷新。

问题描述

经过查询vue文档,可以使用keep-alive实现标签路由缓存,实现方式如下:

在路由配置的meta中添加keepAlive,如下:

{path:'/actdebt',component:Layout,redirect:'/actdebt/add',children:[{path:'add',name:'XXX新增配置',meta:{keepAlive:true,},component:()=>import(/*webpackChunkName:"page"*/'@/views/bankact/actdebt/add')}]},

然后在页面中使用v-if做判断,并且加上key

<keep-alive><router-view:key="$route.fullPath"class="avue-view"v-if="$route.meta.keepAlive"/></keep-alive><router-viewclass="avue-view"v-if="!$route.meta.keepAlive"/>

使用上面这种方式解决了修改不同记录的缓存问题,因为不同记录的fullPath 不一样,这样的话key就会不一样。

但是对于新增和修改同一条记录还是有缓存问题。例如新增一条记录保存成功后,下次在打开新增页面,还是缓存有之前的记录。

修改页面也是的,修改同一条记录保存成功后,再次打开可能还是会有之前的修改数据。

解决方案

要解决上面这种问题我想到的解决方案为:在不同的tag导航栏切换的时候,保留缓存数据。当关闭tag导航栏或者关闭页面的时候,清除缓存。

清除缓存可以在组件里面的deactivated钩子函数调用this.$destroy();但是发现下次打开这个页面的时候,新的组件不会被缓存了。

可以利用keep-alive的include,新打开标签时,把当前组件名加入到include数组里,关闭标签时从数组中删除关闭标签的组件名就可以了。

Include里面的值必须和组件的name属性保持一致,如下:

vue中如何使用keep-alive动态删除已缓存组件

但是如果我同一个组件加载了两次,一个需要缓存,一个不需要缓存。但是他们的name却是一样的,还是无法解决问题。

所以是否可以重写keep-alive源码,使include可以按照路由地址匹配,而不是按照组件的name匹配。完整的代码如下:

新建keepAlive.js文件

vue中如何使用keep-alive动态删除已缓存组件

/***base-keep-alive主要解决问题场景:多级路由缓存*前提:保证动态路由生成的routename值都声明了且唯一*基于以上对keep-alive进行以下改造:*1.组件名称获取更改为路由名称*2.cache缓存key也更改为路由名称*3.pruneCache*/const_toString=Object.prototype.toStringfunctionisRegExp(v){return_toString.call(v)==='[objectRegExp]'}exportfunctionremove(arr,item){if(arr.length){constindex=arr.indexOf(item)if(index>-1){returnarr.splice(index,1)}}}/***1.主要更改了name值获取的规则*@param{*}opts*/functiongetComponentName(opts){//returnopts&&(opts.Ctor.options.name||opts.tag)returnthis.$route.path}functionisDef(v){returnv!==undefined&&v!==null}functionisAsyncPlaceholder(node){returnnode.isComment&&node.asyncFactory}functiongetFirstComponentChild(children){if(Array.isArray(children)){for(leti=0;i<children.length;i++){constc=children[i]if(isDef(c)&&(isDef(c.componentOptions)||isAsyncPlaceholder(c))){returnc}}}}functionmatches(pattern,name){if(Array.isArray(pattern)){returnpattern.indexOf(name)>-1}elseif(typeofpattern==='string'){returnpattern.split(',').indexOf(name)>-1}elseif(isRegExp(pattern)){returnpattern.test(name)}/*istanbulignorenext*/returnfalse}functionpruneCache(keepAliveInstance,filter){const{cache,keys,_vnode}=keepAliveInstancefor(constkeyincache){constcachedNode=cache[key]if(cachedNode){//------------3.之前默认从router-view取储存key值,现在改为路由name,所以这里得改成当前key//constname=getComponentName.call(keepAliveInstance,cachedNode.componentOptions)constname=keyif(name&&!filter(name)){pruneCacheEntry(cache,key,keys,_vnode)}}}}functionpruneCacheEntry(cache,key,keys,current){constcached=cache[key]if(cached&&(!current||cached.tag!==current.tag)){cached.componentInstance.$destroy()}cache[key]=nullremove(keys,key)}constpatternTypes=[String,RegExp,Array]exportdefault{name:'keep-alive',//abstract:true,props:{include:patternTypes,exclude:patternTypes,max:[String,Number]},created(){this.cache=Object.create(null)this.keys=[]},destroyed(){for(constkeyinthis.cache){pruneCacheEntry(this.cache,key,this.keys)}},mounted(){this.$watch('include',val=>{pruneCache(this,name=>matches(val,name))})this.$watch('exclude',val=>{pruneCache(this,name=>!matches(val,name))})},render(){constslot=this.$slots.defaultconstvnode=getFirstComponentChild(slot)constcomponentOptions=vnode&&vnode.componentOptionsif(componentOptions){//checkpatternconstname=getComponentName.call(this,componentOptions)//----------对于没有name值得设置为路由得name,支持vue-devtool组件名称显示if(!componentOptions.Ctor.options.name){vnode.componentOptions.Ctor.options.name}const{include,exclude}=thisif(//notincluded(include&&(!name||!matches(include,name)))||//excluded(exclude&&name&&matches(exclude,name))){returnvnode}const{cache,keys}=this//-------------------储存的key值,默认从router-view设置的key中获取//constkey=vnode.key==null//?componentOptions.Ctor.cid+(componentOptions.tag?`::${componentOptions.tag}`:'')//:vnode.key//-------------------2.储存的key值设置为路由中得name值constkey=nameif(cache[key]){vnode.componentInstance=cache[key].componentInstance//makecurrentkeyfreshestremove(keys,key)keys.push(key)}else{cache[key]=vnodekeys.push(key)//pruneoldestentryif(this.max&&keys.length>parseInt(this.max)){pruneCacheEntry(cache,keys[0],keys,this._vnode)}}vnode.data.keepAlive=true}returnvnode||(slot&&slot[0])}}

然后在main.js中引入该组件,使组件可以全局使用

vue中如何使用keep-alive动态删除已缓存组件

在页面直接使用BaseKeepAlive:

<BaseKeepAlive:include="cachetags"><router-view:key="$route.fullPath"class="avue-view"/></BaseKeepAlive>

cachetags 方法就是新打开标签时,把当前组件名加入到include数组里,关闭标签时从数组中删除关闭标签,源码如下:

computed:{...mapGetters(['isLock',"tagList",'isCollapse','website']),cachetags(){letlist=[]for(letitemofthis.tagList){if(!validatenull(item.keepalive)&&item.keepalive){list.push(item.value)}}returnlist.join(',')}},

方法中的tagList就是导航栏当前打开相应的tag集合如下图所示

vue中如何使用keep-alive动态删除已缓存组件

读到这里,这篇“vue中如何使用keep-alive动态删除已缓存组件”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

本文:vue中如何使用keep-alive动态删除已缓存组件的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:uniapp如何开发安卓App实现高德地图路线规划导航功能下一篇:

4 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18