keep-alive 快速实现页面缓存

<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似, <kceep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。

当组件在 <keep-alive> 内被切换,它的 activateddeactivated 这两个生命周期钩子函数将会被对应执行

Props

include
exclude
max

基本使用

1. 与router配合使用,设置meta属性

给路由设置 meta 属性, keepAlivetrue

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      meta: {
        keepAlive: true
      }
    },
    {
      path: '/a',
      name: 'a',
      component: a,
      meta: {
        keepAlive: true
      }
    }
  ]
})

<keep-alive> 标签包裹路由组件,给路由加上 if 判断

<template>
  <div id="app">
    <keep-alive>
      <router-view v-if="this.$route.meta.keepAlive" />
    </keep-alive>
    <router-view v-if="!this.$route.meta.keepAlive" />
  </div>
</template>

2. 使用 includeexclude

includeexclude 属性是 2.1.0 新增 。 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示

<template>
  <div id="app">
    <keep-alive :include="includeViews">
      <router-view />
    </keep-alive>
  </div>
</template>


<script>
export default {
  name: 'App',
  data() {
    return {
      includeViews: ['a', 'c']
    }
  }
}
</script>

注意:使用 include exclude 属性,路由指向的页面组件一定要设置 name 属性 。 name 设置在组件里,不是路由里面!!!

max 2.5.0 新增

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

<keep-alive :max="10">
    <component :is="view"></component>
</keep-alive>

activated and deactivated

activateddeactivated 这两个生命周期函数一定是要在使用了keep-alive组件后才会存在

当引入 keep-alive 的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated。

我们可将页面只要调用一次的方法放在 createdmounted 里面,每次打开都要调用的函数放在 activated 里面。

deactivated 妙用: keep-alive 并不能缓存页面的滚动位置,所以可以使用 deactivated 来记录页面的滚动距离,在返回页面的时候再取出来即可。

遇到的坑

在我的公司项目中我是在路由里设置了meta。却出现页面缓存之后,进入另个缓存页面时,路径url已经切换,但是页面显示的前一个缓存的页面并触发里面的方法。

场景模拟

  • a,b,c 三个页面,a 与 c 需要缓存。
  • a 进入 b ,再返回 a ,a 成功缓存。
  • a 进入 b ,再进入 c , url已经切换但页面显示的却是缓存的 a 页面
    我在练写demo的时候并没有这种问题,想了很久觉得是 keep-alive 在多个页面缓存时,好像没有区分各个缓存的页面,导致显示错误。所以直接在 router-view 绑定了 key 值,意外解决了这个bug。
<template>
  <div id="app">
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive" :key="$route.fullPath"></router-view>
    </keep-alive>


    <router-view v-if="!$route.meta.keepAlive"/>
  </div>
</template>
我来评几句
登录后评论

已发表评论数()

相关站点

热门文章