Vue提供了keep-alive作为包裹组件来缓存内部的业务组件,使用该组件,能够缓存业务组件的状态,在一些场景里可以提高用户体验和性能,避免重复的请求。
一:用法
<keep-alive include="your-component" exclude="" max="">
<component is="your-component" v-if="show"></component>
</keep-alive>
二:属性介绍
include 定义了需要缓存的组件名,参数可以使用字符串或者正则字符串,例如“a,b” 或者/a|b/
exclude 定义了不需要缓存的组件名, 用法同上
max 定义最大缓存数量,超过max,会默认把最久没有被使用过的从缓存里剔除(见源码注释)
三:核心代码
render: function render () {
var slot = this.$slots.default;
var vnode = getFirstComponentChild(slot); // 默认只取第一个子组件,所以在keep-alive里包裹多个组件只会处理第一个
var componentOptions = vnode && vnode.componentOptions;
if (componentOptions) {
// check pattern
var name = getComponentName(componentOptions);
var ref = this;
var include = ref.include;
var exclude = ref.exclude;
if (
// not included
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(exclude, name))
) {
return vnode // 当判断不在include里 或者在exclude里的组件,直接返回新的vnode,不读取缓存
}
var ref$1 = this;
var cache = ref$1.cache;
var keys = ref$1.keys;
var key = vnode.key == null
// same constructor may get registered as different local components
// so cid alone is not enough (#3269)
? componentOptions.Ctor.cid + (componentOptions.tag ? ("::" + (componentOptions.tag)) : '')
: vnode.key;
if (cache[key]) { // 判断是否有缓存过的
vnode.componentInstance = cache[key].componentInstance;
// make current key freshest
remove(keys, key); // 刚刚使用缓存的vnode 的key会被删除
keys.push(key);// 然后重新添加到末尾,方便max设置后,剔除最旧没有使用过的vnode
} else {
cache[key] = vnode; // 缓存组件的虚拟dom
keys.push(key);
// prune oldest entry
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode); // 剔除数组中的头部缓存
}
}
vnode.data.keepAlive = true; //打上keepAlive的标示,方便其他框架里的逻辑来识别
}
return vnode || (slot && slot[0])
}
};
四:钩子函数
当组件第一次渲染的时候会先跟传统组件一样触发到mounted钩子,然后触发activated钩子。之后就只会触发下面两个钩子。
activated 当前组件处于激活状态,当组件显示的时候触发该钩子
deactivated 当前组件处于非激活状态,当组件隐藏的时候触发该钩子
五:注意事项
不要在keep-alive 同时渲染多个组件,会被忽略,具体原因看源码的注释
keep-alive 里包裹组件的子组件们都会触发activated和deactivate钩子(2.2.0+)版本后
keep-alive是虚拟组件,不会生成任何dom
六:使用场景
需要来回切换的业务场景,(例如tab切换或者路由切换),但是数据更新不是很频繁的页面。为用户保存状态,避免每次切换都重新拉数据进行渲染。可以通过activated钩子来触发部分刷新。