Vue2关于keep-alive详解(2) - 原理篇

173 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情

关于keep-alive的具体用法已在上文做了详解,想要深入了解其具体实现原理,可以查看vue源码地址。本文将逐步分析源码并做一些总结。

组件基础

首先将组件名设置为keep-alive,接收include,exclude,max三个参数,定义abstract属性,该属性决定了keep-alive会不会被渲染到页面上

image.png

接着可以看到keep-alive在它生命周期上定义的三个钩子函数:created,mounted,destroyed

created方法很简单,就是初始化了cache(用来存放缓存组件的虚拟dom集合)和keys(用来存放缓存组件的key的集合)

image.png

mounted方法主要是实时对includeexcluede这两个参数进行监听,并实时更新到cache数组中。pruneCache函数的核心也主要是去调用prueCacheEntry,下文讲到。

image.png

destroyed方法则是删除cache缓存的实例。核心是调用prueCacheEntry进行删除操作。

image.png

重点看prueCacheEntry方法:可以看到,该方法遍历集合去执行所有缓存组件的destory钩子函数,并将cache对应的key设为null,并删除keys中对应的元素。

image.png

render函数

image.png

keep-alive渲染

  • keep-alive它不会生成真正的DOM节点,这是怎么做到的?

image.png

因为Vue初始化生命周期时,源码中为组件实例建立父子关系的时候会根据abstract属性决定是否忽略某个组件。而我们从上文组件基础中可以看到在keep-alive中,设置了abstract: true,那Vue就会跳过该组件实例。

因此在最后构建的组件树中就不会包含keep-alive组件,那么由组件树渲染成的DOM树自然也不会有keep-alive相关的节点了。

  • keep-alive包裹的组件是如何使用缓存的?

image.png

在首次加载被包裹组件时,由上文组件基础的render函数可知,vnode.componentInstance的值是undefined,且keepAlive的值是true,因为keep-alive组件作为父组件,它的render函数会先于被包裹组件执行;那么就只执行到i(vnode, false /* hydrating */),后面的逻辑不再执行;

而当再次访问被包裹组件时,vnode.componentInstance的值就是已经缓存的组件实例,那么会执行insert(parentElm, vnode.elm, refElm)方法,就可以直接把上一次的DOM插入到了父元素中。从而实现缓存。