博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
VUE缓存:动态keep-alive
阅读量:4085 次
发布时间:2019-05-25

本文共 2715 字,大约阅读时间需要 9 分钟。

场景

在最近的开发中,设计有A、B、C三个页面,试想这样一个场景需求:

  • 离开B页面进入C页面,缓存B页面数据(keepAlive: true)
  • 离开B页面进入A页面,不缓存B页面数据(keepAlive: false)

概念

  • keep-alive

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

    • 导航离开该组件的对应路由时调用
    • 可以访问组件实例 this

前置背景:keep-alive 组件实现

  • 路由元信息内添加特定字段如:keepAlive
const router = new VueRouter({  routes: [    {      path: '/foo',      component: Foo,      children: [        {          path: 'bar',          component: Bar,          // a meta field          meta: {             keepAlive: true           }        }      ]    }  ]})复制代码
  • 父组件内根据路由中的keepAlive字段动态使用keep-alive标签
class Home extends Vue {    get keepAlive () {      // 获取当前路由的元信息中的keepAlive字段      return this.$route.meta.keepAlive    }    private render () {      return (        
{ !this.keepAlive &&
}
{ this.keepAlive &&
}
) } } export default Home复制代码

思路

由于现在组件的keep-alive是动态根据路由元信息中的keepAlive字段进行动态使用的,所以只要动态改变对应路由元信息的keepAlive字段就可以实现动态缓存。

实现方案

方案一

  • 利用beforeRouteLeave改变from的keepAlive实现(原思路,网络解决方案之一,有bug)
beforeRouteLeave (to: any, from: any, next: any) {  // 导航离开该组件的对应路由时调用  // 判断是否是去往页面 C   if (to.name !== 'C') {    // 不是去 C 页面,不缓存    from.meta.keepAlive = false  } else {    // 是去 C 页面,缓存    from.meta.keepAlive = true  }  next()}复制代码

bug:首次去C页面,再返回B页面,B并没有缓存,第二次再进入C页面,B页面缓存,且进A页面并不能清除B页面的缓存

方案二(网络方案)

  • $destroy()销毁
beforeRouteLeave (to: any, from: any, next: any) {  // 导航离开该组件的对应路由时调用  // 判断是否是去往页面 C   if (to.name !== 'C') {    // 不是去 C 页面,不缓存    this.$destroy()  }  next()}复制代码

bug:销毁之后永远不会被缓存

方案三(网络方案)

  • 根据源码看来缓存的组件都会设置一个cache属性,可以通过代码强行移除掉。缺点就是没有彻底销毁依旧占内存

方案四(最优解)

  • 利用keep-alive的include属性,利用vuex动态控制include达到动态管理缓存
  • 这边不做赘述,网上有很多相关示例代码,且原理很简单

特殊场景以上方案均不可实现下的解决方案

特殊场景

  • 此次项目为移动端项目,并未用到keep-alive的include属性,且如果要加入,则项目很多配置需要修改,比较麻烦

解决方案

  • 解决方案与上面的方案一类似
  • 区别:
    • 不操作beforeRouteLeave中的from对象改变keepAlive
    • 直接操作this.$router中对应路由元信息的keepAlive
// 操作指定name的路由的元信息private changeKeepAlive (parentName: string, name: string, keepAlive: boolean) {  // @ts-ignore  this.$router.options.routes.map((item: any) => {    if (item.name === parentName) {      item.children.map((a: any) => {        if (a.name === name) {          a.meta.keepAlive = keepAlive        }      })    }  })}beforeRouteLeave (to: any, from: any, next: any) {    // 导航离开该组件的对应路由时调用    // 可以访问组件实例 `this`    if (to.name === 'C') {      this.changeKeepAlive('Home', 'B', true)    } else {      this.changeKeepAlive('Home', 'B', false)    }    next()  }复制代码

经测试,这种解决方案就不会出现方案一的bug

BY--LucaLJX ()

作者:LucaLJX
链接:https://juejin.im/post/5c1cc517e51d45778a5c72c6
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的文章
No.182 - LeetCode1325 - C指针的魅力
查看>>
带WiringPi库的交叉笔译如何处理二之软链接概念
查看>>
Java8 HashMap集合解析
查看>>
自定义 select 下拉框 多选插件
查看>>
Linux常用统计命令之wc
查看>>
fastcgi_param 详解
查看>>
搞定Java面试中的数据结构问题
查看>>
React Native(一):搭建开发环境、出Hello World
查看>>
Winform多线程
查看>>
Spring AOP + Redis + 注解实现redis 分布式锁
查看>>
poj 1976 A Mini Locomotive (dp 二维01背包)
查看>>
《计算机网络》第五章 运输层 ——TCP和UDP 可靠传输原理 TCP流量控制 拥塞控制 连接管理
查看>>
二叉树深度优先遍历和广度优先遍历
查看>>
生产者消费者模型,循环队列实现
查看>>
获得github工程中的一个文件夹的方法
查看>>
《PostgreSQL技术内幕:查询优化深度探索》养成记
查看>>
PostgreSQL查询优化器详解之逻辑优化篇
查看>>
STM32中assert_param的使用
查看>>
字符串的截取
查看>>
Tensorflow入门资料
查看>>