Vue开发--详解keep-alive

prop:

  • include: 字符串或正则表达式。只有匹配的组件会被缓存。2.1.0+
  • exclude: 字符串或正则表达式。任何匹配的组件都不会被缓存( exclude优先级大于include)。2.1.0+
  • max 最多可以缓存多少组件实例 2.5.0+
  • activated 和 deactivate 生命周期钩子
  • 不会在函数式组件中正常工作,因为它们没有缓存实例。
<keep-alive include="a,b" :include="['a','b']" :exclude="/a|b/" :max="10">
  <component :is='view'></component>
</keep-alive>

用法:
是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。

包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

相似,只是一个抽象组件,它不会在DOM树中渲染(真实或者虚拟都不会),也不在父组件链中存在,比如:你永远在 this.$parent 中找不到 keep-alive。

当组件在 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。

// 组件
export default {
  name: 'test-keep-alive',
  data () {
    return {
        includedComponents: "test-keep-alive"
    }
  }
}
<keep-alive include="test-keep-alive">
  <!-- 将缓存name为test-keep-alive的组件 -->
  <component></component>
</keep-alive>

<keep-alive include="a,b">
  <!-- 将缓存name为a或者b的组件,结合动态组件使用 -->
  <component :is="view"></component>
</keep-alive>

<!-- 使用正则表达式,需使用v-bind -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 动态判断 -->
<keep-alive :include="includedComponents">
  <router-view></router-view>
</keep-alive>

<keep-alive exclude="test-keep-alive">
  <!-- 将不缓存name为test-keep-alive的组件 -->
  <component></component>
</keep-alive>

2、结合router,缓存部分页面

使用$route.meta的keepAlive属性:

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

需要在router中设置router的元信息meta:

//...router.js
export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello,
      meta: {
        keepAlive: false // 不需要缓存
      }
    },
    {
      path: '/page1',
      name: 'Page1',
      component: Page1,
      meta: {
        keepAlive: true // 需要被缓存
      }
    }
  ]
})

使用效果,以上面router的代码为例:

// Page1页面
<template>
  <div class="hello">
    <h1>Vue</h1>
    <h2>{{msg}}</h2>
    <input placeholder="输入框"></input>
  </div>
</template>
// Hello页面
<template>
  <div class="hello">
    <h1>{{msg}}</h1>
  </div>
</template>

(1) 在Page1页面输入框输入“asd”,然后手动跳转到Hello页面;

(2) 回到Page1页面发现之前输入的"asd"依然保留,说明页面信息成功保存在内存中;

当然,也可以通过动态设置route.meta的keepAlive属性来实现其他需求,借鉴一下 vue-router 之 keep-alive这篇博客中的例子:

  • 首页是A页面
  • B页面跳转到A,A页面需要缓存
  • C页面跳转到A,A页面不需要被缓存

思路是在每个路由的beforeRouteLeave(to, from, next)钩子中设置to.meta.keepAlive:

A的路由:

{
    path: '/',
    name: 'A',
    component: A,
    meta: {
        keepAlive: true // 需要被缓存
    }
}
export default {
    data() {
        return {};
    },
    methods: {},
    beforeRouteLeave(to, from, next) {
         // 设置下一个路由的 meta
        to.meta.keepAlive = true;  // B 跳转到 A 时,让 A 缓存,即不刷新
        next();
    }
};
export default {
    data() {
        return {};
    },
    methods: {},
    beforeRouteLeave(to, from, next) {
        // 设置下一个路由的 meta
        to.meta.keepAlive = false; // C 跳转到 A 时让 A 不缓存,即刷新
        next();
    }
};

3、keep-alive生命周期钩子函数:activated、deactivated
被包含在 中创建的组件,会多出两个生命周期的钩子: activated 与 deactivated

activated:在组件被激活时调用,在组件第一次渲染时也会被调用,之后每次keep-alive激活时被调用。

deactivated:在组件被停用时调用。

注意:只有组件被包裹时,这两个生命周期才会被调用,如果作为正常组件使用,是不会被调用,以及在 2.1.0 版本之后,使用 exclude 排除之后,就算被包裹在中,这两个钩子依然不会被调用!另外在服务端渲染时此钩子也不会被调用的。

设置了keepAlive缓存的组件:

  • 第一次进入:beforeRouterEnter ->created->…->activated->…->deactivated
  • 后续进入时:beforeRouterEnter ->activated->deactivated

可以看出,只有第一次进入该组件时,才会走created钩子,而需要缓存的组件中activated是每次都会走的钩子函数。所以,我们要在这个钩子里面去判断,当前组件是需要使用缓存的数据还是重新刷新获取数据。

使用会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在activated阶段获取数据,承担原来created钩子中获取数据的任务。

场景 :Vue中前进刷新,后退缓存用户浏览数据

  • 列表页面 =>点击进入详情页=> 后退到列表页 要缓存列表原来数据
  • 重新进入列表页面 => 获取最新的数据
// router.js
{
  path: '/list',
  name: 'List',
  component: List,
  meta: {
    isUseCache: false, // 默认不缓存
    keepAlive: true  // 是否使用 keep-alive
  }
}
// 列表页面
activated() {
  if(!this.$route.meta.isUseCache){ //isUseCache 时添加中router中的元信息,判读是否要缓存
    this.list = [] //清空原有数据
    this.onload() // 重新加载
  }
}

// 列表页面跳转到 详情页时,设置需要缓存
beforeRouteLeave(to, from, next){
  if(to.name=='Detail'){
    from.meta.isUseCache = true
  }
  next()
}
// 列表页面的activated
activated() {
 if(!this.$route.meta.isUseCache){ //isUseCache 时添加中router中的元信息,判读是否要缓存
    this.list = [] //清空原有数据
    this.onload() // 重新加载
  }
 this.$route.meta.isUseCache = false // 通过这个控制刷新
}

你可能感兴趣的:(Vue)