“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

  1. Keep-alive is a built-in component of Vue that preserves the state of contained components and prevents re-rendering
  2. It is used together with routing and dynamic components to cache components.
  3. 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.
  4. 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