vue keepalive 前进刷新后退不刷新终极解决方案

2020-01-17 08:44:57

关于vue keeplive的刷新缓存终极解决方案,就看下面了,全栈网其他关于解决keeplive的大家就当作参考吧。

另外,我们做路由的时候要有意的根据页面等级做出路由的长度 比如 /a是一级的页面/a/b是二级的页面,下面的文章大家也可以通过判断path的长度来计算rank值,不用有意自定了

这样做的好处有两点,一个就是前进刷新,后退不刷新,还有就是,如果我们做页面进出效果的时候也能排上用场。

 遇到这一个个问题  需要是这样的 Vue里面的不刷新问题

页面分为: A 主页  B列表页  C 详情页

A  beforeRouteLeave 时设置 to.meta.keepAlive = false (A 进入 B页面时), 不缓存 B列表页

B beforeRouteLeave 时 (B -> C)列表页进详情页时 from.meta.keepAlive =true 缓存B列表页

C详情页 返回 B列表页 ,此时B列表页缓存不生效,也就是第一次不生效

总结问题原因:

当进入B列表页后,keepAlive 为 true 时,缓存生效

当离开B列表页时 设置 keepAlive 为 true  时 ,缓存不生效

这就是很头疼的问题,查阅相关资料找到

解决

在app.vue 页面

<transition :name="transitionName">
      <keep-alive>
        <!-- v-if="isRouterALive" :include="[ keepData ]" -->
        <router-view class="child-view" v-if="$route.meta.keepAlive" ></router-view>
      </keep-alive>
    </transition>
    <transition :name="transitionName">
      <router-view class="child-view" v-if="!$route.meta.keepAlive"></router-view>
    </transition>

路由页面配置:

{
    path: '/activities/create_proto',
    name: 'create_proto',
    meta: {
      index: 2,
      title: '活动创建',
      keepAlive: false, //此组件不需要被缓存
      rank:1,
    },
    component: () =>
      import (/* webpackChunkName: "create_proto" */'@/pages/activities/create_proto')
  },
  {
    path: '/activities/create/:id',
    name: 'create',
    meta: {
      index: 2,
      title: '活动创建',
      keepAlive: true, //此组件不需要被缓存
      isBack:false, //用于判断上一个页面是哪个
      rank:1.5,
    },
    component: () =>
      import (/* webpackChunkName: "create" */'@/pages/activities/create')
  },

  {
    path: '/activities/createMask',
    name: 'createMask',
    meta: {
      index: 2,
      title: '组',
      keepAlive: false, //此组件不需要被缓存
      isBack:false, //用于判断上一个页面是哪个
      rank:1.5,
    },
    component: () =>
      import (/* webpackChunkName: "createMask" */'@/pages/activities/createMask')
  },

让B页面始终是缓存,

然后在B页面 就是 create页面 里:

beforeRouteEnter(to,from,next){
    //来自editNotic的不缓存
      if(from.name === 'createMask' && to.name === 'create'){
        to.meta.isBack = true;
      }
      next();
    },
    activated() {
    //   console.log(this.$route.meta)
      if(!this.$route.meta.isBack || this.isFirstEnter){
        // 如果isBack是false,表明需要获取新数据,否则就不再请求,直接使用缓存的数据
        this.getApi();
      }
      // 恢复成默认的false,避免isBack一直是true,导致下次无法获取数据
      this.$route.meta.isBack=false;
      //this.isBack = false;
      this.isFirstEnter = false;
    },
    beforeCreate() {
      this.$loading.open();
    },

    mounted(){
      this.isFirstEnter = true;
      this.getApi();
    },

解释一波

缓存的页面 created 会执行只有一次,activated每次都会执行 ,

created 里面做 第一次 isFirstEnter = true(由于页面被缓存,所以一直生效),之后再activated 里面做判断

只有 “不是返回回来的” 和 “第一次进来的” 就刷新数据, 并且要在下面 都设为false, 以免缓存各标识不对,

在进入 “列表页” 时,通过router钩子函数 beforeRouteEnter做判断,

详情页过来的设 isBack 为true,即不刷新页面

 

但第一次都是不生效的,查阅了github 上的大佬方法,就是强制清除B缓存,当B页面离开去到A页面,用rank 来比较

在main.js 中 写入:

Vue.mixin({
  beforeRouteLeave: function (to, from, next) {
    console.log(to)
    if (from && from.meta.rank && to.meta.rank && from.meta.rank > to.meta.rank) { //如果返回上一层,则摧毁本层缓存。
      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();
  },
})

就是强制清除缓存,哇,这个问题搞了半天,

然后就解决了前进刷新,后退不刷的问题,

当然还可以结合vuex 来做到效果,但数据比较大的话还是适合 我写的这种吧,哈哈哈


  • 2019-12-04 10:47:59

    nuxt.js项目中全局捕获异常并生成错误日志全过程

     需求:客户在使用过程中页面报错时,可以生成错误记录传回服务器,以便改进。   步骤:     一.全局捕获异常,     二.发送到服务端,     三.生成错误日志。   一.全局捕获异常 如图,vue提供了errorHandle这个方法来处理全局异常,更多详细内容参见官网。

  • 2019-12-04 10:48:18

    vue 项目资源文件 static 和 assets 不说区别直接使用?

    assets中资源会webpack构建压缩到你代码中,而static文件直接引用。 static 中长存放类包、插件等第三方的文件,assets里放属资源文件比如自己资源图片、css文件、js文件。 引入资源的方式static文件夹可以使用~/static/方式引入, assets文件夹可以使用 ~@/assets 方式引入

  • 2019-12-05 17:01:36

    Vue 结合 Axios 接口超时统一处理

    当网路慢的时候。又或者公司服务器不在内地的时候,接口数据请求不回来超时报错的情况相信大家肯定遇到过的,这里我把我公司项目请求超时的处理方法分享下,希望看过后有帮助。

  • 2019-12-05 17:13:40

    JS模板工具lodash.template的简单用法

    lodash是从underscore分支的一个项目,之前我写了一篇JS模板工具underscore.template的简单用法,lodash跟underscore很相似,这也简单介绍一下lodash的template方法。 先把underscore的文章中用过的代码贴过来,把underscore的js文件换成lodash的js,其他一字不改,然后我们试试:

  • 2019-12-06 10:47:29

    date-fns日期工具的使用方法详解

    isToday() 判断传入日期是否为今天 isYesterday() 判断传入日期是否为昨天 isTomorrow() 判断传入日期是否为 format() 日期格式化 addDays() 获得当前日期之后的日期 addHours() 获得当前时间n小时之后的时间点 addMinutes() 获得当前时间n分钟之后的时间 addMonths() 获得当前月之后n个月的月份 subDays() 获得当前时间之前n天的时间 subHours() 获得当前时间之前n小时的时间 subMinutes() 获得当前时间之前n分钟的时间 subMonths() 获得当前时间之前n个月的时间 differenceInYears() 获得两个时间相差的年份 differenceInWeeks() 获得两个时间相差的周数 differenceInDays() 获得两个时间相差的天数 differenceInHours() 获得两个时间相差的小时数 differenceInMinutes() 获得两个时间相差的分钟数

  • 2019-12-06 10:49:39

    npm 查看源 换源

    npm,cnpm,查看源,切换源,npm config set registry https://registry.npmjs.org

  • 2019-12-06 11:01:31

    npm发布包流程详解 有demo

    npm发布包步骤,以及踩过的坑(见红颜色标准): 1.注册npm账号,并完成Email认证(否则最后一步提交会报Email错误) 2.npm添加用户或登陆:npm adduser 或 npm login

  • 2019-12-06 13:16:18

    vue mixins组件复用的几种方式

    最近在做项目的时候,研究了mixins,此功能有妙处。用的时候有这样一个场景,页面的风格不同,但是执行的方法,和需要的数据非常的相似。我们是否要写两种组件呢?还是保留一个并且然后另个一并兼容另一个呢? 不管以上那种方式都不是很合理,因为组件写成2个,不仅麻烦而且维护麻烦;第二种虽然做了兼容但是页面逻辑造成混乱,必然不清晰;有没有好的方法,有那就是用vue的混合插件mixins。混合在Vue是为了提出相似的数据和功能,使代码易懂,简单、清晰。