使用

  1. <!-- 基本 -->
  2. <keep-alive>
  3. <component :is="view"></component>
  4. </keep-alive>

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

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

原理

  1. /* keep-alive组件 */
  2. export default {
  3. name: 'keep-alive',
  4. /* 抽象组件 */
  5. abstract: true,
  6. props: {
  7. include: patternTypes,
  8. exclude: patternTypes
  9. },
  10. created () {
  11. /* 缓存对象 */
  12. this.cache = Object.create(null)
  13. },
  14. /* destroyed钩子中销毁所有cache中的组件实例 */
  15. destroyed () {
  16. for (const key in this.cache) {
  17. pruneCacheEntry(this.cache[key])
  18. }
  19. },
  20. watch: {
  21. /* 监视include以及exclude,在被修改的时候对cache进行修正 */
  22. include (val: string | RegExp) {
  23. pruneCache(this.cache, this._vnode, name => matches(val, name))
  24. },
  25. exclude (val: string | RegExp) {
  26. pruneCache(this.cache, this._vnode, name => !matches(val, name))
  27. }
  28. },
  29. render () {
  30. /* 得到slot插槽中的第一个组件 */
  31. const vnode: VNode = getFirstComponentChild(this.$slots.default)
  32. const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
  33. if (componentOptions) {
  34. // check pattern
  35. /* 获取组件名称,优先获取组件的name字段,否则是组件的tag */
  36. const name: ?string = getComponentName(componentOptions)
  37. /* name不在inlcude中或者在exlude中则直接返回vnode(没有取缓存) */
  38. if (name && (
  39. (this.include && !matches(this.include, name)) ||
  40. (this.exclude && matches(this.exclude, name))
  41. )) {
  42. return vnode
  43. }
  44. const key: ?string = vnode.key == null
  45. // same constructor may get registered as different local components
  46. // so cid alone is not enough (#3269)
  47. ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
  48. : vnode.key
  49. /* 如果已经做过缓存了则直接从缓存中获取组件实例给vnode,还未缓存过则进行缓存 */
  50. if (this.cache[key]) {
  51. vnode.componentInstance = this.cache[key].componentInstance
  52. // 2.5.0 新增这段逻辑,使用 LRU 策略 make current key freshest
  53. remove(keys, key);
  54. keys.push(key);
  55. }
  56. // 不命中缓存,把 vnode 设置进缓存
  57. else {
  58. this.cache[key] = vnode;
  59. // 2.5.0 新增这段逻辑,LRU 策略的移除。
  60. keys.push(key);
  61. // 如果配置了 max 并且缓存的长度超过了 this.max,还要从缓存中删除第一个
  62. if (this.max && keys.length > parseInt(this.max)) {
  63. pruneCacheEntry(cache, keys[0], keys, this._vnode);
  64. }
  65. }
  66. /* keepAlive标记位 */
  67. vnode.data.keepAlive = true
  68. }
  69. return vnode
  70. }
  71. }
  1. 获取 keep-alive 包裹着的第一个子组件对象及其组件名

    根据设定的 include/exclude(如果有)进行条件匹配,决定是否缓存。不匹配,直接返回组件实例
  2. 根据组件 ID 和 tag 生成缓存 Key,并在缓存对象中查找是否已缓存过该组件实例。如果存在,直接取出缓存值并更新该 key 在 this.keys 中的位置(更新 key 的位置是实现 LRU 置换策略的关键)
  3. 在 this.cache 对象中存储该组件实例并保存 key 值,之后检查缓存的实例数量是否超过 max 的设置值,超过则根据 LRU 置换策略删除最近最久未使用的实例(即是下标为 0 的那个 key)
  4. 最后组件实例的 keepAlive 属性设置为 true,这个在渲染和执行被包裹组件的钩子函数会用到,

LRU 策略

最近最久未使用算法。

每次从内存中找出最久的未使用数据用于置换新的数据。

vue keep-alive的实现原理和缓存策略的更多相关文章

  1. vue 2.0 路由切换以及组件缓存源代码重点难点分析

    摘要 关于vue 2.0源代码分析,已经有不少文档分析功能代码段比如watcher,history,vnode等,但没有一个是分析重点难点的,没有一个是分析大命题的,比如执行router.push之后 ...

  2. 转 vue实现双向数据绑定之原理及实现篇

    转自:https://www.cnblogs.com/canfoo/p/6891868.html vue的双向绑定原理及实现 前言 先上个成果图来吸引各位: 代码:                  ...

  3. Vue数据绑定和响应式原理

    Vue数据绑定和响应式原理 当实例化一个Vue构造函数,会执行 Vue 的 init 方法,在 init 方法中主要执行三部分内容,一是初始化环境变量,而是处理 Vue 组件数据,三是解析挂载组件.以 ...

  4. vue我的总结+转原理

    我的总结 vue:1 mvvm模型,model,view,viewmodel,自底层向上,逐渐增加的模式2 .vue文件 包含html css js 有最近设计原则,将自己需要的放到最近,2 组件化 ...

  5. Vue双向绑定的实现原理系列(三):监听器Observer和订阅者Watcher

    监听器Observer和订阅者Watcher 实现简单版Vue的过程,主要实现{{}}.v-model和事件指令的功能 主要分为三个部分 github源码 1.数据监听器Observer,能够对数据对 ...

  6. vue实现双向数据绑定的原理

    vue实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的. 在MDN上对该方法的说明是:O ...

  7. 梳理vue双向绑定的实现原理

    Vue 采用数据劫持结合发布者-订阅者模式的方式来实现数据的响应式,通过Object.defineProperty来劫持数据的setter,getter,在数据变动时发布消息给订阅者,订阅者收到消息后 ...

  8. vue的双向数据绑定实现原理

    在目前的前端面试中,vue的双向数据绑定已经成为了一个非常容易考到的点,即使不能当场写出来,至少也要能说出原理.本篇文章中我将会仿照vue写一个双向数据绑定的实例,名字就叫myVue吧.结合注释,希望 ...

  9. MySql 缓存查询原理与缓存监控 和 索引监控

    MySql缓存查询原理与缓存监控 And 索引监控 by:授客 QQ:1033553122 查询缓存 1.查询缓存操作原理 mysql执行查询语句之前,把查询语句同查询缓存中的语句进行比较,且是按字节 ...

随机推荐

  1. 题解 P3940 分组

    有些梦想虽然遥不可及,但不是不可能实现.只要我足够的强. 前言 调了挺长时间的,并查集合并的时候需要 find 一下,不然会炸内存.... 解题思路 参考了题解区一篇思路非常好的题解,在这里讲一下自己 ...

  2. NOIP模拟测试3「序列·熟练剖分·建造游乐园(play)」

    ---恢复内容开始--- 序列 刚调出来样例就A了,假装是水题. 因为是乱序,我们要求出来每两项之间最小公比,而不是直接比 求出来每两项之间最小公比,然后扫一遍就完了.(还要注意重复情况) 那么问题就 ...

  3. MAT工具定位分析Java堆内存泄漏问题方法

    一.MAT概述与安装 MAT,全称Memory Analysis Tools,是一款分析Java堆内存的工具,可以快速定位到堆内泄漏问题.该工具提供了两种使用方式,一种是插件版,可以安装到Eclips ...

  4. 精尽Spring Boot源码分析 - 序言

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  5. Kubernetes使用Keda进行弹性伸缩,更合理利用资源

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 Kubernetes自带的HPA是只支持CPU/MEM的,很多时候我们并不根据这两项指标来进行伸缩资源.比如消费 ...

  6. Ubuntu配置apt安装源为清华源[含自动配置脚本]

    Ubuntu配置apt安装源为清华源[含自动配置脚本] 一.备份原配置文件 Ubuntu 的软件源配置文件是/etc/apt/sources.list.将系统自带的该文件做个备份,以防万一. sudo ...

  7. 流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

    一.背景 之前写过的几个WPF小工具,每次发布都需要给它打安装包和升级包,涉及到一些系列繁琐的手工操作,有了Power Automate Desktop,于是便寻思着能不能做成一个自动化的流来使用. ...

  8. 深入学习Netty(2)——传统NIO编程

    前言 学习Netty编程,避免不了从了解Java 的NIO编程开始,这样才能通过比较让我们对Netty有更深的了解,才能知道Netty大大的好处.传统的NIO编程code起来比较麻烦,甚至有遗留Bug ...

  9. 02 jumpserver系统设置

    2.系统设置: (1)基本设置: (2)邮件设置: 1)163邮箱设置: 2)在jumpserver上填写邮箱信息: 3)邮件测试信息如下: (3)邮件内容设置: (4)终端设置: (5)安全设置:

  10. 29、html介绍

    29.1.前端概述: 1.html.css.js之间的关系: html是页面布局,css是页面渲染,js是让页面动起来(让页面和用户进行交互): 2.浏览器访问web站点获取html页面图示: 3.h ...