Skip to main content
Practice Problems

Dynamic components in Vue.js

What are Dynamic Components?

Dynamic components allow you to switch between different components at the same mount point using the built-in <component> element with the :is attribute.


Basic Usage

vue
<script setup> import { ref, shallowRef } from 'vue' import TabHome from './TabHome.vue' import TabSettings from './TabSettings.vue' import TabProfile from './TabProfile.vue' const tabs = { home: TabHome, settings: TabSettings, profile: TabProfile } const currentTab = shallowRef(TabHome) </script> <template> <div class="tabs"> <button v-for="(comp, name) in tabs" :key="name" :class="{ active: currentTab === comp }" @click="currentTab = comp" > {{ name }} </button> </div> <component :is="currentTab" /> </template>

With String Names

vue
<script setup> import { ref } from 'vue' // Components must be registered globally or locally const currentView = ref('HomeView') </script> <template> <component :is="currentView" /> </template>

With KeepAlive

Preserve state when switching between dynamic components:

vue
<template> <KeepAlive> <component :is="currentTab" /> </KeepAlive> </template>

Passing Props and Events

vue
<template> <component :is="currentComponent" :title="title" :data="componentData" @submit="handleSubmit" @close="handleClose" /> </template>

Practical Example: Form Builder

vue
<script setup> import { shallowRef } from 'vue' import TextInput from './TextInput.vue' import SelectInput from './SelectInput.vue' import CheckboxInput from './CheckboxInput.vue' import TextareaInput from './TextareaInput.vue' const fieldComponents: Record<string, any> = { text: TextInput, select: SelectInput, checkbox: CheckboxInput, textarea: TextareaInput, } const formFields = [ { type: 'text', name: 'name', label: 'Name' }, { type: 'select', name: 'role', label: 'Role', options: ['Admin', 'User'] }, { type: 'checkbox', name: 'active', label: 'Active' }, { type: 'textarea', name: 'bio', label: 'Bio' }, ] </script> <template> <form> <div v-for="field in formFields" :key="field.name"> <component :is="fieldComponents[field.type]" :label="field.label" :name="field.name" v-bind="field" /> </div> </form> </template>

HTML Elements as Dynamic Components

vue
<script setup> const tag = ref('h1') </script> <template> <!-- Renders as <h1>, <h2>, <p>, etc. --> <component :is="tag">Dynamic Heading</component> </template>

shallowRef for Components

typescript
// ✅ Use shallowRef for component references const currentComponent = shallowRef(TabHome) // ❌ Don't use ref — it makes the component deeply reactive (unnecessary) const currentComponent = ref(TabHome) // Unnecessary deep reactivity

Important:

Dynamic components with <component :is="..."> let you switch components at the same mount point. Use shallowRef to store component references. Combine with <KeepAlive> to preserve state. Common use cases: tabs, form builders, plugin systems, and rendering different components based on data.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems