primers

When I wrote Vue before, I wanted to implement a Tab switching component, and I usually used V-if and V-else, and I didn’t think there was anything wrong with it, nor did I think about optimization. Until I was asked about dynamic components in the interview, I didn’t know that dynamic components could be used for this kind of switching requirement, so I wrote an article to record it. This article describes the respective implementations of both approaches, as well as keep-alive.

V-if, V-else mode

Let’s start with a general Tab page implementation.

<template>
    <div>
        <button @click='fa'>A</button>
        <button @click='fb'>B</button>
        <aaa v-if="show"></aaa>
        <bbb v-else></bbb>

    </div>
</template>
<script>
    //@ is an alias to /src
    import aaa from './a';
    import bbb from './b';
    export default {
        name: 'XXX',
        components: { aaa, bbb },
        data() {
            return {
                show: true
            }
        },
        methods: {
            fa() {
                this.show = true
            },
            fb() {
                this.show = false
            }
        },
    }
</script>
<style lang="less">
</style>
Copy the code

This will do the trick, but we need to write as many V-else ifs as there are components. The amount of code is still relatively large, and with more components, the multi-layer nested loop is also ugly, so many judgments are ugly from the code style, and a bunch of logic together is also ugly.

Dynamic component, is mode

Let’s look at the dynamic component approach:

// Parent component <template> <div> < button@click ='fa'>A</button> < button@click ='fb'>B</button> <component :is="currentComp"></component> </div> </template> <script> //@ is an alias to /src import aaa from './a'; import bbb from './b'; export default { name: 'XXX', data() { return { currentComp: aaa } }, methods: { fa() { this.currentComp = aaa }, fb() { this.currentComp = bbb } } } </script> <style lang="less"> </style>Copy the code

The Component tag is a built-in Vue tag with an IS property that can be used for component switching. As you can see, with the dynamic component approach, we only need to write a Component tag. We don’t need multiple layers of if-else nesting. Not only that, if you use dynamic components, you can skip the step of registering in the Component object after import. You can just do it in the data.

Keep-alive

By this point, you are already familiar with simple dynamic components. Now the question is, will dynamic components be cached? When using V-if /else, each switch goes to the component’s destroyed() phase of the lifecycle. What lifecycle does the dynamic component switch go to? Let’s see.

<script> //@ is an alias to /src export default{ name: 'A', destroyed () {the console. The log (' destruction of A ')}, the data () {return {}}, components: {}} < / script >Copy the code
<script> //@ is an alias to /src export default{ name: 'A', destroyed () {the console. The log (' destruction of A ')}, the data () {return {}}, components: {}} < / script >Copy the code

Add an output to component A’s destroyed phase and component B’s Destroyed phase to see if they are destroyed.

In practice, dynamic component switching destroys switched components just like V-IF.

This leads to a problem. If there is a submitted form on the page, the user can switch, lose it, and then switch back and have to re-enter it, leading to a poor user experience. This is where we can use keep-alive to ensure that the component will not be destroyed.

All keep alive

// Parent <keep-alive> <component :is="currentComp"/> </keep-alive>Copy the code

In this way, the components used will not be destroyed, and all components that have been switched will be cached and not destroyed, and the form content of each component will remain.

Local keep alive

However, caching a large number of components can sometimes cause performance problems. What if we only want to cache specific components? The official API documentation shows that keep-Alive provides three attributes include, exclude and Max.

You can set which components to cache, which not to cache, and the maximum number of components to cache. For example, cache only component A:

// @is an alias to/SRC export default{name: 'aa1, destroyed () {the console. The log (' destruction of A')}, the data () {return {}}, components: {}} < / script >Copy the code
<keep-alive include="aa1"> <component :is="currentComp"/> </keep-alive>Copy the code

We first need to set the A component’s name property, which can be used by include and exclude. The include and exclude attributes support regular:

<component :is="currentComp"/> </keep-alive>Copy the code

Also, if it is a tag like video, setting keep-alive will keep it playing in the background.

Keep alive – principle

Cache object, keys array and slot.

if ( // not included (include && (! name || ! matches(include, name))) || // excluded (exclude && name && matches(exclude, name)) ) { return vnode }Copy the code

SRC /core/components/keep-alive.js file.