前言
组件的生命周期:
默认情况下,一个组件实例在被替换掉后会被销毁。这会导致它丢失其中所有已变化的状态 —— 当这个组件再一次被显示时,会创建一个只带有初始状态的新实例
Vue 的渲染机制:
具体的渲染步骤如下:
- template
- AST(directives, props, attrs, events...)
- js 逻辑(过滤)
- filtered AST
- vNode (虚拟节点)
- vDOM (虚拟DOM)
- 真实 DOM ( rDOM )
Vue 的更新机制:
每一次视图更新:
- 每一次更新的 vNode 和上一次的 vNode 进行比较
- 对比之后产生差异(diff)
- 在有差异的地方打上补丁(patch)
- 根据补丁(patch)更新视图
但是,每一次更新比较渲染都要先判断此组件实例是否被缓存(isKeepAlive ?)
什么是 <KeepAlive>
<KeepAlive>是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例, 并在内部建立KeepAlive和这些组件之间的映射关系。
和 <KeepAlive>相关的两个生命周期钩子
activated:<KeepAlive>包裹的的组件活跃时触发- deactivated:
<KeepAlive>包裹的的组件失活时触发
注意:
不要乱用keep-alive逻辑 ! ($forceUpdate是一个逃生舱)
KeepAlive上的属性
exclude: 按照组件的name属性, 不缓存此name属性(局部注册组件名称)的组件, 其余缓存include: 按照组件的name属性, 缓存此name属性(局部注册组件名称)的组件, 其余不缓存
include & exclude使用注意
- include & exclude 都是通过name属性(局部注册组件名称)进行查找并缓存组件的
- 使用类型: 字符串, 数组(v-bind:include="['']"), 正则表达式 (/n|c/)
- 字符串形式后面不可以有空格
- 推荐使用数组的形式, 便于维护
-
max: 最多能够缓存的组件实例的个数, 超过组件实例会删除缓存时间最久的组件<KeepAlive>的行为在指定了max后类似一个 LRU 缓存:如果缓存的实例数量即将超过指定的那个最大数量,则最久没有被访问的缓存实例将被销毁,以便为新的实例腾出空间。
异步组件和KeepAlive一起使用可能存在的问题
- 异步组件一开始不会被
<KeepAlive>缓存 include不能缓存使用异步组件(只能使用exclude)- 建议异步组件不要和
<KeepAlive>一起使用
KeepAlive的实现思路
思路, 缓存 vNode ( Vue 源码缓存的是component instance)
判断 vNode 是否为 keepAlive ?
-
是, 直接去compCache里面的值
-
否, 创建一个新的节点: 并判断创建出来的节点是否在缓存中 ?
- 是:写入缓存
- 不是: 不写入缓存