1551天 瑾忆

重要的人越来越少,剩下的人也越来越重要 ​​

Vue缓存机制keep-alive之踩坑

发布于 5个月前 / 597 次围观 / 4 条评论 / 杂七杂八 / 瑾忆

目的:A -> B -> C,处于B页面时,如果是前进也就是到C页面,B的页面数据保留(缓存),从C回到B,B还是原来的亚子,B -> A就把B的缓存干掉,A -> B 时B是全新的(初始化/刷新),emmm大概就是要这么个效果。

有点像小程序那样子的效果

App.vue

<keep-alive>
      <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>

方案一

直接在B上写

beforeRouteLeave(to, from, next) {
      //c仅为示例,可以自行采用相应的判断
      if (to.path == 'c') {
        from.meta.keepAlive = true;
      } else {
        from.meta.keepAlive = false;
      }
      next();
}

这个写法是有问题,第一次是没有被缓存的,第二次才会产生缓存,然而keepAlive = false时并没有让缓存移除。

方案二

在A -> B时就让B keepAlive = true,这样第一次打开B就可以让其产生缓存,当然也可以写在路由里,但写在路由里并不是我想要的。

A.vue

beforeRouteLeave(to, from, next) {
      let paths = ["/category", "/console", "/order"];
      //paths 是我需要产生缓存的路由地址
      if (paths.includes(to.path)) {
        to.meta.keepAlive = true;
      }
      next();
}

B.vue

 beforeRouteLeave(to, from, next) {
    if (to.path == 'c') {
      //B->C    B照样缓存
      from.meta.keepAlive = true;
    } else {
      //不是前进到C的话就关闭,这个关闭和方案一一样,没卵用
      from.meta.keepAlive = false;
      //所以加多一个强制销毁
      this.$destroy();
    }
    next();
  }

这时大致看起来就是哪个效果了,理论上是正确了的,但强行销毁this.$destroy();后keepAlive = true缓存就废了,就再也无法缓存,具体什么问题我也不知道。

方案三最佳食用方式

这个具体请看官方文档https://cn.vuejs.org/v2/api/#keep-alive

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <router-view></router-view>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <router-view></router-view>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <router-view></router-view>
</keep-alive>

这玩意害人不浅啊,一开始我以为include里填的是路由里的name,结果include毫无作用,跟放屁一样,我都以为他在骗我了,还是说我姿势不对,最后还是选择度娘一下(使用include/exclude 属性需要给所有vue类的name赋值(注意不是给route的name赋值),否则 include/exclude不生效)沃特???QQ图片20200525221903.jpg

giao,虽然知道了食用方式,但对于这么多没有name的vue项目里,再一个个搞是真的很麻烦,没办法技术有限,放弃最佳食用方式

方案四暴力方式

A.vue与方案二的一样

B.vue

 beforeRouteLeave(to, from, next) {
    if (to.path.indexOf("/category/") != -1) {
      from.meta.keepAlive = true;
    } else {
      from.meta.keepAlive = false;
      //暴力清除缓存
      if (this.$vnode && this.$vnode.data.keepAlive) {
        if (
          this.$vnode.parent &&
          this.$vnode.parent.componentInstance &&
          this.$vnode.parent.componentInstance.cache
        ) {
          if (this.$vnode.componentOptions) {
            var key =
              this.$vnode.key == null
                ? this.$vnode.componentOptions.Ctor.cid +
                  (this.$vnode.componentOptions.tag
                    ? `::${this.$vnode.componentOptions.tag}`
                    : "")
                : this.$vnode.key;
            var cache = this.$vnode.parent.componentInstance.cache;
            var keys = this.$vnode.parent.componentInstance.keys;
            if (cache[key]) {
              if (keys.length) {
                var index = keys.indexOf(key);
                if (index > -1) {
                  keys.splice(index, 1);
                }
              }
              delete cache[key];
            }
          }
        }
      }
      this.$destroy();//如果不加这个强制销毁,你会发现缓存虽然没有了,但它还是存在内存中,而且每返回一次就增加一条
    }
    next();
  }

最后发现暴力方式正好实现了我想要的效果,缓存也没有多余,一切正常。

  1. 3周前 (09-29)
    @

    谢谢分享,日常打卡~  滴滴~

  2. 3个月前 (07-25)
    @

    大佬就是大佬

  3. 5个月前 (05-28)
    @

    不愧是忆忆,真棒

    • 5个月前 (06-01)
      @ NO
      fjk

      @夜灭:真棒