11

问题很常见,简单来说就是A,B,C三个页面。
A>B不缓存,C>B需要缓存。
想着记得之前网上看过,就一顿操作。

在路由里面加上了
    {
      path: '/b',
      name: 'B',
      component: B,
      meta:{
        keepAlive:true
      }
    }
    
   
 在app.vue写了

 <keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
 </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
    
  A页面写了
 beforeRouteLeave(to, from, next) {
    to.meta.keepAlive = false;
    next();
  }
C页面写了
beforeRouteLeave(to, from, next) {
    to.meta.keepAlive = true;
    next();
  }  

以为没事了。结果一测试发现。
第一次A>B>C,之后再返回B的话,不会被缓存。
从B到A,之后到B,B没被缓存,表现正常,之后点击C,这个时候从C返回,得到的是一开始B的缓存。

折腾半天,发现还是解决不掉。
最后终于发现一个完美的方法。

利用include,动态添加"B"

步骤如下:
1、在app.vue下增加keep-alive

<keep-alive :include="catchList">
   <router-view></router-view>
</keep-alive>

这里的catchList,是vuex维护的需要缓存的组件名的一个数组
2、在路由中加入

router.beforeEach((to, from, next) => {
  if (to.name === 'B') {
    store.commit('keepAlive', 'B')
  }
  next()
})

3、在b.vue中加入

beforeRouteLeave (to, from, next) {
    if (to.name !== 'C') {
        this.$store.commit('noKeepAlive')
    }
    next()
  }

备注,在vuex中mutation是

keepAlive(state, component) {
    !state.catchList.includes(component) &&
      state.catchList.push(component)
  },
  noKeepAlive(state) {
    state.catchList = []
  }

大致的原理是,只要是B的组件,都缓存。只有当从B>A的时候,才让B不缓存。
亲测同原理,但是meta.keepAlive会出现其他bug
所以,目前来看,能用的方法,其实只有这一种。
网上大量的设置meta的方法,亲测都存在问题,不知道是都没注意到还是都是copy的。

第二天更新

今天看了下keep-alive源码,证实了meta.keepAlive=true这种方法,解决不了条件缓存问题

原因:在keep-alive源码中,include和exclude是被watch的,当发生变化时,keep-alive会去校验cache里是否匹配,匹配不上的会被删除。也就是说,官方是为这种情况做了处理的。而meta这种方法,因为没有存在某种类似于watch的方法,导致这种方法天然是和实际cache里面的内容有出入的,所以可定会存在各种奇怪的bug。


barry
78 声望1 粉丝