JAVASCRIPT
Rendering Dynamic Components with Vue 3 `<component :is />`
Learn to dynamically switch between different components at runtime using Vue 3's `<component :is />`, perfect for tabbed interfaces, wizards, or configurable UI.
// TabA.vue
<template>
<div class="tab-content">
<h3>Content for Tab A</h3>
<p>This is the first tab's specific information. It could be complex forms or data displays.</p>
<input type="text" placeholder="Input specific to Tab A">
</div>
</template>
// TabB.vue
<template>
<div class="tab-content">
<h3>Content for Tab B</h3>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<button>Action in Tab B</button>
</div>
</template>
// App.vue
<template>
<div class="tabs-container">
<div class="tab-buttons">
<button
v-for="tab in tabs"
:key="tab.name"
@click="activeTab = tab.component"
:class="{ active: activeTab === tab.component }"
>
{{ tab.name }}
</button>
</div>
<div class="tab-panel">
<!-- The magic happens here: render the component bound to activeTab -->
<component :is="activeTab" />
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import TabA from './TabA.vue';
import TabB from './TabB.vue';
const activeTab = ref(TabA); // Start with TabA active
const tabs = [
{ name: 'Tab A', component: TabA },
{ name: 'Tab B', component: TabB },
];
</script>
<style scoped>
.tabs-container { border: 1px solid #ddd; border-radius: 5px; padding: 15px; max-width: 600px; margin: 20px auto; }
.tab-buttons { display: flex; margin-bottom: 15px; }
.tab-buttons button {
padding: 10px 15px;
border: 1px solid #ccc;
background-color: #f9f9f9;
cursor: pointer;
border-radius: 5px 5px 0 0;
margin-right: -1px; /* Overlap borders */
font-weight: bold;
}
.tab-buttons button:last-child { margin-right: 0; }
.tab-buttons button.active {
background-color: #fff;
border-bottom-color: #fff;
z-index: 1;
position: relative;
}
.tab-panel {
border: 1px solid #ddd;
border-top: none;
padding: 20px;
background-color: #fff;
border-radius: 0 0 5px 5px;
min-height: 100px;
}
.tab-content { animation: fadein 0.3s; }
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }
</style>
How it works: This snippet illustrates how to use Vue 3's special `<component :is />` attribute to dynamically render different components based on a reactive state. In `App.vue`, `activeTab` holds a reference to a component definition (`TabA` or `TabB`). When a button is clicked, `activeTab` updates, and `<component :is="activeTab" />` automatically renders the corresponding component. This is highly useful for building flexible UI elements like tabbed interfaces, step-by-step wizards, or dashboard widgets where the content dynamically changes without requiring `v-if` chains.