Dynamically show a Vue component

By

Learn how to dynamically show or hide a Vue component based on your app state, using v-if, v-else, and the component element with is in Vue 3.

~~~

To dynamically show a component in Vue 3, 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 setup>
import { computed, ref } from 'vue'

const todos = ref([])

const noTodos = computed(() => todos.value.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.

The same pattern with Options API:

<script>
export default {
  data() {
    return {
      todos: [],
    }
  },
  computed: {
    noTodos() {
      return this.todos.length === 0
    }
  }
}
</script>

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 (or :is):

<component :is="currentView"></component>

currentView can be a string name of a registered component, or a component object itself:

<script setup>
import { shallowRef } from 'vue'
import PanelA from './PanelA.vue'
import PanelB from './PanelB.vue'

const currentView = shallowRef(PanelA)

function showB() {
  currentView.value = PanelB
}
</script>

Change currentView and Vue swaps the rendered component. This is great for tabs: one placeholder, many possible panels. For the basics of building those pieces as single file components, start there if you haven’t yet.

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 :is="currentView"></component>
</keep-alive>

If the switch itself is driven by a button click, wire that with a method.

Tagged: Vue.js · All topics

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about vue: