1. What is Keep-alive
Keep-alive is a built-in component in vue. It can retain state in memory during component switching, preventing repeated rendering of DOM.
Keep-alive When wrapping dynamic components, it caches inactive component instances instead of destroying them.
Keep-alive can be set as followsprops attribute:
- include - String or regular expression. Only components with matching names will be cached
- exclude - String or regular expression. Any component with a name matching will not be cached
- max - Number. How many component instances can be cached at most
aboutkeep-alive
Basic usage:
<keep-alive> <component :is="view"></component> </keep-alive>
useincludes
andexclude
:
<keep-alive include="a,b"> <component :is="view"></component> </keep-alive> <!-- Regular expressions (use `v-bind`) --> <keep-alive :include="/a|b/"> <component :is="view"></component> </keep-alive> <!-- Array (use `v-bind`) --> <keep-alive :include="['a', 'b']"> <component :is="view"></component> </keep-alive>
First check the component's ownname
Options, ifname
The option is not available, then it matches its local registration name (parent componentcomponents
The key value of the option), the anonymous component cannot be matched
The component with keep-alive cache is set, and there will be two additional life cycle hooks (activated
anddeactivated
):
- When entering a component for the first time: beforeRouteEnter > beforeCreate > created > mounted > activated > ... ... > beforeRouteLeave > deactivated
- When entering the component again: beforeRouteEnter > activated > ... > beforeRouteLeave > deactivated
2. Use scenarios
Principle of use: When we do not need to reload the page in certain scenarios, we can usekeepalive
Take a chestnut:
When we return from home page –> list page –> trade details page –> then the list page should need to keep-alive
From home page –> list page –> trade details page –> return to list page (need to cache) –> return to home page (need to cache) –> enter the list page again (no cache required), and you can control the keep-alive of the page as needed.
Set keepAlive attribute in the route to determine whether cache is required
{ path: 'list', name: 'itemList', // List page component (resolve) { require(['@/pages/item/list'], resolve) }, meta: { keepAlive: true, title: 'List Page' } }
use<keep-alive>
<div class='wrapper'> <keep-alive> <!-- View components that require cache --> <router-view v-if="$"></router-view> </keep-alive> <!-- 不View components that require cache --> <router-view v-if="!$"></router-view> </div>
3. Principle analysis
keep-alive
yesvue
A built-in component
Source code location: src/core/components/
export default { name: 'keep-alive', abstract: true, props: { include: [String, RegExp, Array], exclude: [String, RegExp, Array], max: [String, Number] }, created () { = (null) = [] }, destroyed () { for (const key in ) { pruneCacheEntry(, key, ) } }, mounted () { this.$watch('include', val => { pruneCache(this, name => matches(val, name)) }) this.$watch('exclude', val => { pruneCache(this, name => !matches(val, name)) }) }, render() { /* Get the first component node in the default slot */ const slot = this.$ const vnode = getFirstComponentChild(slot) /* Get componentOptions for this component node */ const componentOptions = vnode && if (componentOptions) { /* Get the name of the node of the component, and priority is obtained for the name field of the component. If the name does not exist, get the tag of the component */ const name = getComponentName(componentOptions) const { include, exclude } = this /* If the name is not in inlcude or exists in exlude, it means that it is not cached and directly returns vnode */ if ( (include && (!name || !matches(include, name))) || // excluded (exclude && name && matches(exclude, name)) ) { return vnode } const { cache, keys } = this /* Get the key value of the component */ const key = == null // same constructor may get registered as different local components // so cid alone is not enough (#3269) ? + ( ? `::${}` : '') : /* After getting the key value, go to the object to find out whether the value is present. If so, it means that the component has a cache, that is, hit cache */ if (cache[key]) { = cache[key].componentInstance // make current key freshest remove(keys, key) (key) } /* If there is no hit cache, set it into cache */ else { cache[key] = vnode (key) // prune oldest entry /* If max is configured and the cache length exceeds, delete the first one from the cache */ if ( && > parseInt()) { pruneCacheEntry(cache, keys[0], keys, this._vnode) } } = true } return vnode || (slot && slot[0]) } }
You can see that the component does not havetemplate
, but usedrender
, will be automatically executed when the component is renderedrender
function
Is an object used to store components that need to be cached, and it will be stored in the following form:
= { 'key1':'Component 1', 'key2':'Component 2', // ... }
Execute when component is destroyedpruneCacheEntry
function
function pruneCacheEntry ( cache: VNodeCache, key: string, keys: Array<string>, current?: VNode ) { const cached = cache[key] /* Determine that there is no component currently in the rendered state and destroy it*/ if (cached && (!current || !== )) { .$destroy() } cache[key] = null remove(keys, key) }
existmounted
Observation in hook functioninclude
andexclude
The changes are as follows:
mounted () { this.$watch('include', val => { pruneCache(this, name => matches(val, name)) }) this.$watch('exclude', val => { pruneCache(this, name => !matches(val, name)) }) }
ifinclude
orexclude
There has been a change, that is, the rules that define the components that need to be cached or the rules that do not need to be cached have changed, then it will be executed.pruneCache
Functions, the functions are as follows:
function pruneCache (keepAliveInstance, filter) { const { cache, keys, _vnode } = keepAliveInstance for (const key in cache) { const cachedNode = cache[key] if (cachedNode) { const name = getComponentName() if (name && !filter(name)) { pruneCacheEntry(cache, key, keys, _vnode) } } } }
The object is traversed within this function, the name value of each item is taken out, and the new cache rule is used to match it. If the match is not up, it means that the component does not need to be cached under the new cache rule. Then call the pruneCacheEntry function to remove it from the object
The most powerful cache function about keep-alive is implemented in the render function
First get the key value of the component:
const key = == null? + ( ? `::${}` : '') :
Get itkey
Go after it's worth itLook for whether the value is present in the object. If so, it means that the component has a cache, that is, hit cache, as follows:
/* If the cache is hit, take the vnode component instance directly from the cache */ if (cache[key]) { = cache[key].componentInstance /* Adjust the order of the component key, delete it from the original place and re-place it in the last */ remove(keys, key) (key) }
Get it directly from the cachevnode
Component instance, then readjust the componentkey
In order, delete it from the original place and replace itThe last one
There is no such object
key
The value situation is as follows:
/* If there is no hit cache, set it into cache */ else { cache[key] = vnode (key) /* If max is configured and the cache length exceeds, delete the first one from the cache */ if ( && > parseInt()) { pruneCacheEntry(cache, keys[0], keys, this._vnode) } }
Indicates that the component has not been cached yet, then the component'skey
as keys, componentsvnode
is a value, save it inand
key
Savemiddle
Then make a judgmentWhether the number of cache components in the file exceeds the maximum cache number set
, if it exceeds, delete the first cache component
4. How to get data after cache
There are two solutions:
beforeRouteEnter
actived
actived
beforeRouteEnter
Every time the component is rendered, it will be executedbeforeRouteEnter
beforeRouteEnter(to, from, next){ next(vm=>{ (vm) // Every time you enter the route execution () // Get data }) },
actived
existkeep-alive
When the cached component is activated, it will be executedactived
hook
activated(){ () // Get data},
Note: During server-side renderingavtived
Not called
This is the article about the syntax and principle analysis of the Keep-Alive cache component usage in Vue. For more related contents of the keep-Alive cache component, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!