keep-alive使用笔记

115 阅读2分钟

概念

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

作用

在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性。

<!-- 失活的组件将会被缓存!-->
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>

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

  • activated:如果使用keep-alive缓存,每次进入页面时需要执行的代码可以放在这里

Props

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  • max - 数字。最多可以缓存多少组件实例。
    • 最多可以缓存多少组件实例。一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。
 <!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>


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


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


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

使用

切换当前路由时,内容会被缓存,页面将保留之前的操作状态

<keep-alive>
    <router-view></router-view>
</keep-alive>
    window.sessionStorage.setItem('fydz/sub/list', true);

注意

  • 问题
    • 在多层级使用时,如三级页面,前两个层级需要缓存,多次在层级上转换时会有问题
  • 问题详述
    • 在第一次进入第一、二层级后,点击从三级回到二级或从二级回到三级,页面会保持原状,但再次点进一、二级后,页面内容不会更新
  • 修改bug需要刷新页面
    • 点击进入页面而不是返回,却不更新是bug,因此需要在进入页面时刷新页面(或初始化、更新页面数据)
  • 修改方案
    • 错误做法:在进入页面时传参,如第一层设置this.$route.query.isFresh = true,在第二层级的activated里面判断是否刷新,此时第三层级点击返回后,由于第二层级的query上带有isFresh=true,且子层级改不了,页面会一直刷新
    • 正确方案:使用sessionstorage作为是否刷新的判断
      • 第一层级
window.sessionStorage.setItem('fydz/sub/list', true);
  • 第二层在activated中
if (window.sessionStorage.getItem('fydz/sub/list') && window.sessionStorage.getItem('fydz/sub/list') === 'true') {
  this.init();
}
  • 第三层中的返回方法写
if (window.sessionStorage.getItem('fydz/sub/list')) {
    window.sessionStorage.setItem('fydz/sub/list', false);
}
// 或者
if (window.sessionStorage.getItem('fydz/sub/list')) {
    window.sessionStorage.removeItem('fydz/sub/list');
}
  • 注意要在第二层中写removeItem删除sessionStorage
beforeDestroy() {
    if (window.sessionStorage.getItem('fydz/sub/list')) {
        window.sessionStorage.removeItem('fydz/sub/list');
    }
}

 

ps:this.init()里面需要包括初始化传参、初始化data,初始化请求等各种操作;同时需要添加一个flag:freshPage,刷新vue页面(:key="freshPage")