认识
一、认识
Vue.js 3.0
中, KeepAlive
可以避免一个组件被频繁地销毁和重建。KeepAlive
本质是缓存管理, 再加上特殊的挂载和卸载逻辑。KeepAlive
实现逻辑如下所示:
const KeepAlive = {
props: {
max: Number,
include: RegExp,
exclude: RegExp
},
setup(props,setupContext){
const { slots } = setupContext;
……,
return ()=>{
let rawVNode = slots.default();
const cache = new Map(); // key: rawVNode.type, value: rawVNode
……,
return rawVNode 或者 cache.get(rawVNode.type);
}
}
}
由上所示, KeepAlive
组件本身不会渲染额外内容, KeepAlive
的工作是对在 组件VNode
对象上添加一些标记属性,以便渲染器能够依据这些标记属性执行特定的逻辑。 KeepAlive
的渲染函数最终只返回需要被 KeepAlive
的组件
二、标记细节
KeepAlive
的工作是对在 组件VNode
对象上添加一些标记属性,以便渲染器能够依据这些标记属性执行特定的逻辑。标记属性 如下所示
2.1 keptAlive
keptAlive
标记组件是否已经被缓存。如果 keptAlive
为 true
时, 组件需要重新渲染的时候, 渲染器并不会重新挂载它, 而是将它激活。
const processComponent = (n1, n2, container, anchor) => {
if (n1 == null) {
if (n2.keptAlive) {
n2.keepAliveInstance._activate(n2, container, anchor);
} else {
mountComponent(n2, container, anchor);
}
} else {
updateComponent(n1, n2, container, anchor);
}
};
2.2 keepAliveCtx
keepAliveCtx
是 KeepAlive
组件实例独有属性。存入move
函数、createElement
函数等。基本逻辑如下所示:
function mountComponent(vnode, container, anchor){
……,
/**
* @description: 组件实例
*/
const instance = {
state,
attrs,
slots,
mounted: [],
subTree: null,
isMounted: false,
keepAliveCtx: null,
props: shallowReactive(props)
};
const isKeepAlive = vnode.type.__isKeepAlive;
if (isKeepAlive) {
instance.keepAliveCtx = {
move(vnode, container, anchor) {
insert(vnode.component.subTree.el, container, anchor);
},
createElement
};
}
……
}
2.3 shouldKeepAlive
shouldKeepAlive
属性会添加到组件的 VNode
对象上, 这样当渲染器卸载组件时, 可以通过检查该属性得知该组件需要被 KeepAlive
,因此组件不会真的被卸载,而是调用 _deActivate
完成卸载。
const unmount = vnode => {
if (vnode.type === Fragment) {
vnode.children.forEach(c => unmount(c));
return;
} else if (typeof vnode.type === 'object') {
if (vnode.shouldKeepAlive) {
vnode.keepAliveInstance._deActivate(vnode);
} else {
unmount(vnode.component.subTree);
}
return;
}
const parent = vnode.el.parentNode;
if (parent) {
parent.removeChild(vnode.el);
}
}
2.4 keepAliveInstance
keepAliveInstance
组件 VNode
对象会持有 KeepAlive
组件的实例, 在 unmount
函数中会通过 keepAliveInstance
来访问 _deActivate
函数。
三、激失细节
3.1 激活
instance._activate = (vnode, container, anchor) => {
move(vnode, container, anchor);
};
激活 的本质是将组件所渲染的内容移动到隐藏容器中
3.2 失活
instance._deActive = vnode => {
move(vnode, storageContainer);
};
失活 的本质是将组件所渲染的内容从隐藏容器中搬运回原来的容器
四、属性细节
4.1 include
include
用于显式地配置应该被缓存的组件
4.2 exclude
exclude
用于显式地配置不应该被缓存的组件
五、缓存细节
Vue.js 3.0
使用 LRU
缓存淘汰策略管理组件缓存。新缓存的组件 或者 被访问的缓存组件 放到第一项, 当缓存超过 max
阈值时, 删除最后一项(即最长时间没被访问)的组件。