资讯专栏INFORMATION COLUMN

vue中keepAlive的使用

Anleb / 3291人阅读

摘要:文档在及其更高版本中,和将会在树内的所有嵌套组件中触发。另外,在我们的项目中遇到路由相同但参数不同的情况组件被复用,不更新的问题,官方给出了响应路由参数变化根据参数数据响应

前言

在开发中经常有从列表跳到详情页,然后返回详情页的时候需要缓存列表页的状态(比如滚动位置信息),这个时候就需要保存状态,要缓存状态;vue里提供了keep-alive组件用来缓存状态。
可以用以下几种方案解决问题;

一、利用meta标签

直接上代码,
1、首先在路由中的meta标签中记录keepAlive的属性为true

    path: "/classify",
    name: "classify",
    component: () => import("@/views/classify/classify.vue"),
    meta: {
      title: "雷石淘券券",
      keepAlive: true
    }
  },

2、在创建router实例的时候加上scrollBehavior方法

export default new Router({
  mode: "history",
  base: process.env.BASE_URL,
  routes,
  scrollBehavior (to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    } else {
      return {
        x: 0,
        y: 0
      }
    }
  }
})

3/在需要缓存的router-view组件上包裹keep-alive组件


   

4、由于有些情况下需要缓存有些情况下不需要缓存,可以在缓存的组件里的路由钩子函数中做判断

beforeRouteLeave (to, from, next) {
    this.loading = true
    if (to.path === "/goods_detail") {
      from.meta.keepAlive = true
    } else {
      from.meta.keepAlive = false
     // this.$destroy()
    }
    next()
  },

支持可以支持组件的缓存,但是这种方法有bug,首先第一次打开页面的时候并不缓存,即第一次从列表页跳到详情页,再回来并没有缓存,后面在进入详情页才会被缓存
并且只会缓存第一次进入的状态,不会重新请求数据,如果当页面A选中一个分类跳到B页面,再从B列表页面跳往详情页,此时会缓存这个状态,并且以后再从A页面的其他分类跳到B页面都不会重新被缓存,以至于每次从详情页返回B页面都会跳第一次缓存的状态;当你的项目只有一种状态需要缓存,可以考虑使用这种方法

二 使用include、exclude属性和beforeRouteEnter钩子函数

首先介绍一下include和exclude vue文档(https://cn.vuejs.org/v2/api/#...
是在vue2.0以后新增的属性
include是需要缓存的组件;
exclude是除了某些组件都缓存;
include 和 exclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示:

    

  




  




  

匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配。

max只在2.5.0新增,最多可以缓存多少组件实例。一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。


  
activated 与 deactivated。

简单介绍一下在被keep-alive包含的组件/路由中,会多出两个生命周期的钩子:activated 与 deactivated。
文档:在 2.2.0 及其更高版本中,activated 和 deactivated 将会在 树内的所有嵌套组件中触发。
activated在组件第一次渲染时会被调用,之后在每次缓存组件被激活时调用。
activated调用时机:
第一次进入缓存路由/组件,在mounted后面,beforeRouteEnter守卫传给 next 的回调函数之前调用:

beforeMount=> 如果你是从别的路由/组件进来(组件销毁destroyed/或离开缓存deactivated)=>mounted=> activated 进入缓存组件 => 执行 beforeRouteEnter回调

因为组件被缓存了,再次进入缓存路由/组件时,不会触发这些钩子:// beforeCreate created beforeMount mounted 都不会触发。

deactivated:组件被停用(离开路由)时调用
使用了keep-alive就不会调用beforeDestroy(组件销毁前钩子)和destroyed(组件销毁),因为组件没被销毁,被缓存起来了。
这个钩子可以看作beforeDestroy的替代,如果你缓存了组件,要在组件销毁的的时候做一些事情,你可以放在这个钩子里。
如果你离开了路由,会依次触发:

组件内的离开当前路由钩子beforeRouteLeave => 路由前置守卫 beforeEach =>全局后置钩子afterEach => deactivated 离开缓存组件 => activated 进入缓存组件(如果你进入的也是缓存路由

项目中缓存使用方法:
1、在创建的router对象上加scrollBehavior方法,同上;
2、将需要缓存的组件加在include属性里


      

3、在beforeRouteEnter的next回掉函数里,对返回A页面不需要缓存的的情况初始化,即将本来需要写在created里的东西写在这里;注意一定要将所有的需要初始化的数据要写一遍,不然会有bug;所以不太推荐

beforeRouteEnter (to, from, next) {
    next(vm => {
      // 通过 `vm` 访问组件实例
      if (from.path !== "/goods_detail") { // 一定是从A进到B页面才刷新
        vm.titleText = vm.$route.query.name
        vm.categoryUpper = vm.$route.query.categoryUpper
        vm.goods = []
        vm.page = 1
        vm.catsIndex = 0
        vm.is_search = false
        vm.getCats2()// 是本来写在created里面的各种
      }
    })
  }
三、使用include、exclude属性和beforeRouteLeave钩子函数和vuex (推荐使用)

第三种方法和第二种相似,不同的地方在于,将需要缓存的组件保存到全局变量,可以在路由的钩子函数里灵活的控制哪些组件需要缓存,那些不需要缓存;跟第二种方法相比,不需要每次再重新初始化数据,但是需要在vuex中保存数据;
上代码
1、在创建的router对象上加scrollBehavior方法,同上;
2、将需要缓存的组件加在include属性里


      

3、在store里加入需要缓存的的组件的变量名,和相应的方法;

export default new Vuex.Store({
  state: {
    catch_components: []
  },
mutations:{
    GET_CATCHE_COMPONENTS (state, data) {
      state.catch_components = data
    }
}
})

3、在beforeRouteLeave钩子函数里控制需要缓存的组件

beforeRouteLeave (to, from, next) { //要在离开该组件的时候控制需要缓存的组件,否则将出现第一次不缓存的情况
    this.busy = true
    if (to.path === "/goods_detail") { // 去往详情页的时候需要缓存组件,其他情况下不需要缓存
      this.$store.commit("GET_CATCHE_COMPONENTS", ["home"])
    } else {
      this.$store.commit("GET_CATCHE_COMPONENTS", [])
    }
    next()
  },

以上是在vue项目里使用keep-alive的情况,网上有一些配合this.$destroy()方法使用的,但我在使用过程中验证了,并不好用;如果有多个状态,并且有选择的缓存,那么第三个方法是最好的选择;如果你不想用vuex使用第二种方法也可以,但需要注意初始化数据。

另外,在我们的项目中遇到路由相同但参数不同的情况组件被复用,不更新的问题,vue官方给出了 响应路由参数变化

watch: {
    "$route" (to, from) {
      document.title = this.$route.query.name
      this.getDefault() //根据参数数据响应
    }

  },

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105122.html

相关文章

  • JS每日一题:vuekeepalive怎么理解?

    摘要:问中怎么理解说在前面是源码中实现的一个组件感兴趣的可以研究源码什么是我们平时开发中总有部分组件没有必要多次我们需要将组件进行持久化,使组件状态维持不变,在下一次展示时,也不会进行重新音译过来就是保持活着所以在中我们可以使用来进行组件缓存基 20190212问 vue中keepalive怎么理解? 说在前面: keep-alive是vue源码中实现的一个组件, 感兴趣的可以研究源码 ht...

    fsmStudy 评论0 收藏0
  • Vue keepAlive 数据缓存工具,实现返回上一个页面浏览位置;

    摘要:需求分析背景数据列表页,滚动加载数据多条数据情况下,点击某一条,进入详细页进行编辑修改,删除操作保存返回上一页在上面的情况下,想要保持在上次浏览位置,并且保持数据是最新的解决办法原始的办法在点击详情页的时候,记住浏览位置,传递参数或者存到本 需求分析 背景:1.数据列表页,滚动加载数据;2.多条数据情况下,点击某一条,进入详细页进行编辑(修改,删除)操作;3.保存返回上一页; 在上面的...

    everfly 评论0 收藏0
  • Cesium3D在多个单页面应用,内存只增不减致内存溢出问题解决

    摘要:解决思路既然每访问一次就会一个,那能不能就创造一个全局的,让他一直存在,通过显示与隐藏去控制在每个单页面应用中的显示呢。 1、背景: 项目使用的语言是vue+iview,因为用到了3D,所以找公司买了3d地图的产品,但是问题随之而来。把我们项目需要用到的3d地图封装成一个组件叫3dMap.vue,方便各个页面调用,vue的工作机制是在离开当前页面的时候把当前页面进行销毁,但是由于C...

    zlyBear 评论0 收藏0
  • 彻底揭秘keep-alive原理

    摘要:我们留意到,这里不是简单地将置为,而是遍历调用函数删除。执行组件的钩子函数删除缓存还要对应执行组件实例的钩子函数。这个在不可忽视钩子函数章节会再次出场。参考技术揭秘源码一、前言 原文链接:github.com/qi... 本文介绍的内容包括: keep-alive用法:动态组件&vue-router keep-alive源码解析 keep-alive组件及其包裹组件的钩子 keep-a...

    lavnFan 评论0 收藏0

发表评论

0条评论

Anleb

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<