keep-alive 的简单应用

keep-alive 的简单应用

业务场景

用户浏览某个数据列表,当数据列表数量很大或者有许多筛选/搜索条件时,点击查看详情然后返回,需要回到离开这个列表时的状态;

  • 如果数据量过大,会使接口返回速度以及渲染速度变慢,导致页面出现长时间白屏或卡顿;
  • 如果需要保存大量的筛选/搜索条件、分页等内容,则需要进行较为繁琐的操作(将内容进行存储或者作为参数传递)

使用 keep-alive 则可以较为简单的解决这些问题;

keep-alive 简介

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

生命周期
  • activated:被 keep-alive 缓存的组件激活时调用,该钩子在服务器端渲染期间不被调用;
  • deactivated:被 keep-alive 缓存的组件停用时调用,该钩子在服务器端渲染期间不被调用;

tip:仅当组件被包裹在 keep-alive 中才会触发

Props (可接受的参数)
  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  • max - 数字。最多可以缓存多少组件实例。

tip:include 和 exclude prop 允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示;

例子

在路由 (router) 文件中找到需要缓存的页面,在 meta 添加 一个属性 keepAlive 作为是否需要缓存的标识

// App.vue
<keep-alive :include="include">
  <!-- 需要缓存的视图组件 --> 
  <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<!-- 不需要缓存的视图组件 -->
<router-view v-if="!$route.meta.keepAlive"></router-view>
// router.js
export default new Router({
  routes: [
    {
      path:'/',
      name:'HelloWorld',
      meta: {
        keepAlive: true,
      }
    },
    {
      path:'/home',
      name:'home',
      meta: {
        keepAlive: false,
      }
    },
  ]
})
产生的问题

当页面有多个同级的数据列表,并且其中部分列表可以查看详情时,使用上面的代码会导致同级的数据列表之前进行切换也会进行缓存;

但是在实际的使用中仅在查看详情的时候需要进行缓存,在同级数据列表切换时数据是需要更新的;

需要使用 include 或者 exclude 进行处理,如下:

// App.vue
<keep-alive :include="include">
  <router-view></router-view>
</keep-alive>
// router.js
// 给路由 (router) 文件的相关页面添加一个字符 level,使用该字段区分该页面是详情页面还是数据列表页面
export default new Router({
  routes: [
    {
      path:'/',
      name:'HelloWorld',
      meta: {
        keepAlive: true,
        level: 1,
      }
    },
    {
      path:'/home',
      name:'home',
      meta: {
        keepAlive: false,
        level: 2,
      }
    },
    {
      path:'/home2',
      name:'home2',
      meta: {
        keepAlive: false,
        level: 1,
      }
    },
  ]
})
export default {
  name: 'App',
  data() {
    return {
      include: [],
    }
  },
  watch: {
    $route(to, from) {
      console.log('to', to)
      console.log('from', from)
      

      // 方案1 根据系统,将 router 下的所以路由地址进行分级(例如设备管理(1),设备详情(2)),从 1 -> 2则进行缓存
      // 实现方法 给 router 的 meta 添加 level 字段,分级如1,2,3
      // 方案1---------------------------------------- start
      // 如果要 to(进入) 的页面是需要 keepAlive 缓存的,把 name push 进 include数组
      // if (to.meta.keepAlive) {
      //   if (!this.include.includes(to.name)) {
      //     this.include.push(to.name)
      //   }
      // }
      // if (from.meta.keepAlive && to.meta.level <= from.meta.level) { // 如果进行的是返回或者是同级跳转的操作则清空
      //   let index = this.include.indexOf(from.name);
      //   if (index !== -1) {
      //     this.include.splice(index, 1);
      //   }
      // }
      // 方案1------------------------------------------ end

      // 方案2 直接判断从 to 跳转到 from 是否是要实现缓存的功能(例如 设备管理 -> 查看)
      // 方案2---------------------------------------- start
      if (to.meta.keepAlive) {
        if (!this.include.includes(to.name)) {
          this.include.push(to.name)
        }
      }
      if (from.meta.keepAlive && from.name === 'HelloWorld' && to.name !== 'home') {
        let index = this.include.indexOf(from.name);
        if (index !== -1) {
          this.include.splice(index, 1);
        }
      }
      // 方案2---------------------------------------- end
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值