“This is the 22nd day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”
Keep alive – use
- Keep-alive is a built-in component of Vue that preserves the state of contained components and prevents re-rendering
- It is used together with routing and dynamic components to cache components.
- Provide include and exclude attributes. Both of them support strings or regular expressions. Include indicates that only components with matching names will be cached, and exclude indicates that components with matching names will not be cached.
- The hook function activated is activated when a component is activated, and the hook function deactivated is activated when a component is removed.
Realize the principle of
We can analyze it from the source code
SRC /core/components/keep-alive.js
export default {
name: 'keep-alive'.abstract: true.// Determining whether the current component's virtual DOM is rendered is the key to the DOM
props: {
include: patternTypes, // Cache whitelist
exclude: patternTypes, // Cache blacklist
max: [String.Number] // The maximum number of component instances cached
},
created () {
this.cache = Object.create(null) // Cache the virtual DOM
this.keys = [] // A cache of virtual DOM keys
},
destroyed () {
for (const key in this.cache) { // Delete all caches
pruneCacheEntry(this.cache, key, this.keys)
}
},
mounted () {
// Monitor whitelist changes in real time
this.$watch('include'.val= > {
pruneCache(this.name= > matches(val, name))
})
this.$watch('exclude'.val= > {
pruneCache(this.name= >! matches(val, name)) }) }, render () {/ /...}}Copy the code
During the Created life cycle, the cache object and keys object are initialized, and keys are used to hold the corresponding VNode key set
During the Destroyed lifecycle, removing the cached VNode also requires the deStory hook function that executes the component instance.
// src/core/components/keep-alive.js
function pruneCacheEntry (
cache: VNodeCache,
key: string,
keys: Array<string>, current? : VNode) {
const cached = cache[key]
if(cached && (! current || cached.tag ! == current.tag)) { cached.componentInstance.$destroy()// Execute the component's destory hook function
}
cache[key] = null
remove(keys, key)
}
Copy the code
Mounted Listens for include and exclude arguments, and updates (deletes) the this.cache in real time. The core of the pruneCache function is also to call pruneCacheEntry.
// src/core/components/keep-alive.js
render () {
const slot = this.$slots.default
const vnode: VNode = getFirstComponentChild(slot) // Find the first child component object
constcomponentOptions: ? VNodeComponentOptions = vnode && vnode.componentOptionsif (componentOptions) { // Component parameters exist
// check pattern
constname: ? string = getComponentName(componentOptions)/ / component name
const { include, exclude } = this
if ( // Condition match
// not included(include && (! name || ! matches(include, name))) ||// excluded
(exclude && name && matches(exclude, name))
) {
return vnode
}
const { cache, keys } = this
constkey: ? string = vnode.key ==null // Define the component's cache key
// 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]) { // This component is already cached
vnode.componentInstance = cache[key].componentInstance
// make current key freshest
remove(keys, key)
keys.push(key) // Adjust the key sort
} else {
cache[key] = vnode // Cache component objects
keys.push(key)
// prune oldest entry
if (this.max && keys.length > parseInt(this.max)) {
// If the number of caches exceeds the limit, delete the first one (LRU cache algorithm)
pruneCacheEntry(cache, keys[0], keys, this._vnode)
}
}
vnode.data.keepAlive = true // Hook functions are used to render and execute wrapped components
}
return vnode || (slot && slot[0])}Copy the code
So the principle of keep-alive can be divided into the following steps:
- Gets the first child component object wrapped around Keep-Alive and its component name
- Include /exclude (if any) is matched to determine whether to cache. Does not match and returns the component instance directly
- The cache Key is generated based on the component ID and tag, and the cache object is looked up to see if the component instance has been cached. If so, fetch the cached value and update the key’s position in this.keys (updating the key’s position is the key to implement the LRU substitution strategy)
- If not, store the component instance in this.cache and the key. Then check if the number of cached instances exceeds the Max value.
- Finally, the keepAlive property of the component instance is set to true, which is used in the rendering and execution of the wrapped component’s hook function