问题遇到的现象和发生背景
A页面,B页面通过路由管理打开了,做切换动作,这时候B页面被KeepAlive缓存了,来回切换,B页面缓存很成功,A页面未做缓存操作,这时候A页面中有个按钮(带着条件),点击跳转B页面,需要清除B页面的缓存,然后A,B页面切换,B页面是缓存的最新的
运行结果
从一个非缓存界面跳转到一个缓存界面,在组件路由设置keepalive为false,离开这个页签后,再返回这个页签,是上上次打开的缓存
我想要达到的结果
可以直接用首页按钮打开界面的缓存覆盖第一次缓存,或者第一次缓存在点击首页按钮的时候清除
** 问题相关代码**
import Vue from 'vue'
import {setStore, getStore} from '@/utils/storage'
import store from './store';
Vue.mixin({
beforeRouteEnter: function (to, from, next) {
if(!to.path.includes('detail')&&to.path!='/normal/occupation'&&to.path!='/normal/ltc'&&to.path!='/authority/frontPageMgmt'
&&!to.path.includes('wel')
&&to.path!='/saber/payment'
&&to.path!='/saber/submitVoucher'
&&to.path!='/saber/orderDetail'
&&to.path!='/system/apvl-proc-config/index'
&& to.path != '/normal/flow/step'
) {
to.meta.keepAlive = true
}
if(to.params&&to.params.from&&(to.params.from=='first'||to.params.from=='fealther')) {
to.meta.keepAlive = false
}
next(() => {
let avueView = document.getElementById('avue-view');
if (avueView && to.meta.savedPosition) {
avueView.scrollTop = to.meta.savedPosition
}
})
},
beforeRouteLeave: function (to, from, next) {
console.log(this)
let avueView = document.getElementById('avue-view');
if (from && from.meta.keepAlive) {
if (avueView) {
from.meta.savedPosition = avueView.scrollTop
}
const result = this.$route.meta.keepAlive === true && store.state.tags.tagList.some(ele => {
return ele.value === this.$route.fullPath;
});
if (this.$vnode && !result) {
from.meta.savedPosition = 0
if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache) {
if (this.$vnode.componentOptions) {
let key = this.$vnode.key == null
? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
: this.$vnode.key;
let cache = this.$vnode.parent.componentInstance.cache;
let keys = this.$vnode.parent.componentInstance.keys;
if (cache[key]) {
if (keys.length) {
let index = keys.indexOf(key);
if (index > -1) {
keys.splice(index, 1);
}
}
delete cache[key];
}
}
}
}
}
//按钮清缓存
if(getStore({name: 'clearTag'})){
if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache) {
if (this.$vnode.componentOptions) {
let key = this.$vnode.key == null
? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
: this.$vnode.key;
let cache = this.$vnode.parent.componentInstance.cache;
let keys = this.$vnode.parent.componentInstance.keys;
if(keys.length>0){
//删除所有,清除缓存
if(getStore({name: 'clearTag'})=='all'||getStore({name: 'clearTag'})=='cache'){
Object.keys(cache).forEach((item)=>{
console.log("item",item,keys,key)
if(cache[item]){
delete cache[item];
}
})
this.$vnode.parent.componentInstance.cache = {};
this.$vnode.parent.componentInstance.keys = []
}else{
//关闭其他
Object.keys(cache).forEach((item,i)=>{
if(cache[item]&&key!=item){
delete cache[item];
keys.splice(i, 1);
}
})
}
}
}
}
setStore({name: 'clearTag', content: ''})
}
next();
},
});
我可以这么理解吗?如果点击首页跳转进来的,就不缓存,如果点击页签进来的,就缓存。
如果是我上面所理解的那样,那可以这么做:
首先,你需要在keep-alive添加两个属性,include和exclude,且是v-bind修饰的,即:include与:exclude,绑定路由跳转过来所带的的某个标志,如果是路由跳转过来的,即点击首页过来的,那就让exclude绑定B组件的名字,否则就为空。
同理,如果是点击页签进来的,那就让include绑定B组件的名字,否则就为空。
include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
加下判断
我理解应该是没问题的,你的意思应该是vuex配合keepAlive的include的实现。这也是一条思路:我按照你的思路简单写了个项目,在清除的缓存的那次切换还是有点问题。其实吧,include和v-if判断keepAlive底层实现类似的,你看我这种思路还有挽救嘛。我写的这个demo是否也能挽救?可能思路有问题,请指正,十分感谢