小菜鸟的keep-alive源码及相关知识

58 阅读3分钟

keep-alive

keep-alive基础知识

keep-alive是vue内置的一个组件

  • Props

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

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

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

abstract: true

源码解析

屏幕截图 2022-09-22 192817.png

props

支持正则/字符串/数组形式的inclue/exclude值,用以缓存特定的值

max为可以缓存的最大组件数目 屏幕截图 2022-09-22 202343.png

created/mounted/destroyed生命周期函数

created初始化的时候创建缓存对象与keys数组(数组存储所有组件的key)

mounted挂载真实dom的时候,创建用户watcher,当include/excluede有不需要缓存的组件,就直接销毁掉并且清空缓存。

destoryed,当keep-alive组件销毁的时候销毁所有的组件,清空所有的缓存。

render函数

因为组件是抽象组件,所以不会渲染视图。 render不渲染的方法:直接返回子组件vnode实例即可。

  1. 该子组件不符合缓存条件,直接return 子组件vnode

  2. 如果符合缓存条件就,查看缓存中是否有该组件缓存,如果有缓存就直接读取;否则就添加缓存。

  3. 如果缓存的组件个数超过了用户定义的max个就销毁组件。

屏幕截图 2022-09-22 210106.png

屏幕截图 2022-09-22 210211.png

data.keepAlive的作用

1. 搭配VueRouter使用

在之前的VueRouter源码解析(三):router-link/router-view组件文章中,也提到了keep-alive。文章中也说了如果,父组件有data.keepAlive属性,就会读取父组件的缓存。

2. 生命周期钩子actived/deactived

当组件内有data.keepAlive的时候,组件data.hook属性就会调用用户添加的actived/deactived回调函数。

matches

正则与数组的方法

屏幕截图 2022-09-22 210620.png

pruneCacheEntry

作用就是清除keep-alive组件的函数。

其参数分别为组件的缓存(this.cache),目标组件的key,缓存过的组件的keys(this.keys),当前渲染的组件vnode。

特别注意的是除了超过最大缓存数max的其他情况清除缓存都是只有三个参数。

而清理超过最大缓存组件的时候会传入第四个参数,这是考虑到队列的第一个组件与当前渲染的组件tag相同的情况,避免调用调用组件destroy钩子。但是缓存还是会删除

屏幕截图 2022-09-22 211219.png

pruneCache

这里就是自定义watcher的回调函数。对于不符合inclue或者符合exclude条件的组件都会从缓存中清除。

屏幕截图 2022-09-22 211453.png

用法

<!-- 逗号分隔字符串 --> 
<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> 

参考文章: Vue源码解析之Keep-alive 作者: Simplyme0823