Dynamically show a Vue 2 component
By Flavio Copes
Learn how to dynamically show or hide a Vue 2 component based on your app state, using the v-if and v-else directives to switch what appears on the page.
To dynamically show a component in Vue 2, you have two main tools: the v-if / v-else directives for conditional rendering, and the component element with is for swapping components in a single spot.
Let’s see both.
Using conditional directives
The simplest option is to use the v-if and v-else directives.
Here’s an example. The v-if directive checks the noTodos computed property, which returns false if the state property todos contains at least one item:
<template>
<main>
<AddFirstTodo v-if="noTodos" />
<div v-else>
<AddTodo />
<Todos :todos=todos />
</div>
</main>
</template>
<script>
export default {
data() {
return {
todos: [],
}
},
computed: {
noTodos() {
return this.todos.length === 0
}
}
}
</script>
When the app starts, todos is empty, so the user sees AddFirstTodo. As soon as an item is added, the condition flips and Vue renders the other branch.
This allows to solve the needs of many applications without reaching for more complex setups. Conditionals can be nested, too, like this:
<template>
<main>
<Component1 v-if="shouldShowComponent1" />
<div v-else>
<Component2 v-if="shouldShowComponent2" />
<div v-else>
<Component3 />
</div>
</div>
</main>
</template>
What about v-show?
v-show looks similar but works differently. v-if removes the component from the DOM and destroys it. v-show keeps it in the DOM and toggles its CSS display property.
If you toggle something often, v-show is cheaper, because Vue doesn’t destroy and recreate the component every time. If the condition rarely changes, v-if is fine and avoids rendering things the user may never see.
Using the component Component and is
Instead of creating v-if and v-else structures, you can build your template so that there’s a placeholder that will be dynamically assigned a component.
That’s what the component component does, with the help of the v-bind:is directive.
<component v-bind:is="componentName"></component>
componentName is a property of the state that identifies the name of the component that we want to render. It can be part of the state, or a computed property:
<script>
export default {
data() {
return {
componentName: 'aComponent',
}
}
}
</script>
Change componentName and Vue swaps the rendered component. This is great for tabs: one placeholder, many possible panels.
Watch out for lost state
Be careful with one thing: when v-if or component is switches a component away, that component is destroyed. Any local state it held is gone. Come back to a tab and the form the user half-filled is empty.
The fix is wrapping the dynamic component in keep-alive, which caches the instances instead of destroying them:
<keep-alive>
<component v-bind:is="componentName"></component>
</keep-alive>