This is the 10th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

<div id="app">
    <button @click="changeTabs('child1')">child1</button>
    <button @click="changeTabs('child2')">child2</button>
    <keep-alive>
        <component :is="chooseTabs">
        </component>
    </keep-alive>
</div>

Copy the code

The use of keep-alive requires adding a tag to the outermost layer of the dynamic component.

Keep alive – principle

In its implementation, keep-Alive internally maintains a key array and a cache object.

Created () {this.cache = object.create (null) this.keys = []},Copy the code

The key array records the component key currently cached. If the component does not specify a key value, a unique key value is automatically generated

The cache object is used to cache the virtual DOM corresponding to the component, with the key as the key and the vNode as the value

In keep-Alive’s rendering function, the basic logic is to determine whether the currently rendered VNode has a corresponding cache. If so, the corresponding component instance will be read from the cache, and if not, it will be cached.

When the number of caches exceeds the value set by Max, keep-alive removes the first element in the key array

render () { const slot = this.$slots.default; Const vNode = getFirstComponentChild(slot); Const name = getComponentName(vnode.componentOptions); Const {cache, keys} = this; // Get the current array of objects and keys const key:? string = vnode.key == null ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '') : vnode.key; // Get the component's key. If there is no key, If (cache[key]) {vnode.componentInstance = cache[key]. ComponentInstance remove(keys, key); // Delete the key value // add the key value to the end of the array to ensure that the most recently used components are later in the array. Key.push (key)} else {// Cache [key] = vnode key.push (key) // Prune simple entry if (this.max && keys.length > parseInt(this.max)) { Remove cache pruneCacheEntry(cache, keys[0], keys, this._vnode) } } vnode.data.keepAlive = true } return vnode || (slot && slot[0]) }Copy the code

conclusion

Whether built-in or user-defined, components are essentially treated the same way when compiled into the Render function from a template, and the details are not covered here. The final result of the render function for keep-alive is as follows:

With the (this) {... _c (' keep alive - '{attrs: {" include ":" child2 "}}, [_c (chooseTabs, {tag: "component"})], 1)}Copy the code

_c(‘keep-alive’···); createElement (Vnode); Therefore,createComponent is called to create a child Vnode. CreateComponent has been analyzed before. The difference between this process and creating a normal Vnode is that the keep-alive Vnode will remove redundant attributes. Since keep-alive attributes other than slot attributes have no meaning inside the component, such as class styles,
, etc., it makes sense to strip out redundant attributes at the Vnode layer.

is deprecated in versions 2.6 and above.