JAVASCRIPT
Swapping Dynamic Components in Vue 3 with the `is` Attribute
Understand how to dynamically switch between different components at runtime in Vue 3 using the special `is` attribute on the `<component>` element.
// src/components/HomeView.vue
<template>
<div>
<h2>Home View</h2>
<p>Welcome to the home page!</p>
</div>
</template>
<script setup>
// Optional: Define a name for better debugging
defineOptions({ name: 'HomeView' });
</script>
// src/components/AboutView.vue
<template>
<div>
<h2>About View</h2>
<p>Learn more about us here.</p>
</div>
</template>
<script setup>
defineOptions({ name: 'AboutView' });
</script>
// src/components/ContactView.vue
<template>
<div>
<h2>Contact View</h2>
<p>Get in touch with us.</p>
</div>
</template>
<script setup>
defineOptions({ name: 'ContactView' });
</script>
// src/App.vue
<template>
<div>
<h1>Dynamic Component Example</h1>
<nav>
<button @click="activeComponent = HomeView">Home</button>
<button @click="activeComponent = AboutView">About</button>
<button @click="activeComponent = ContactView">Contact</button>
</nav>
<div class="component-container">
<!--
The <component> element renders the component specified by its 'is' prop.
It's good practice to wrap dynamic components in <KeepAlive>
to preserve their state when switching between them.
-->
<KeepAlive>
<component :is="activeComponent" />
</KeepAlive>
</div>
</div>
</template>
<script setup>
import { ref, markRaw } from 'vue';
// Import components directly to use their references in `activeComponent`
import HomeView from './components/HomeView.vue';
import AboutView from './components/AboutView.vue';
import ContactView from './components/ContactView.vue';
const activeComponent = ref(HomeView); // Initialize with the HomeView component reference
// Alternatively, you could use component names as strings if they are globally registered
// or if you map them manually. When using string names with `defineAsyncComponent`,
// you would typically need to register them globally or pass them through props.
// Example using string names (less common with direct imports in setup script):
/*
const componentMap = {
HomeView: markRaw(HomeView),
AboutView: markRaw(AboutView),
ContactView: markRaw(ContactView),
};
const activeComponentName = ref('HomeView');
const currentComponent = computed(() => componentMap[activeComponentName.value]);
*/
// When assigning component objects directly, it's often good practice to use markRaw
// if you don't need the component object itself to be reactive.
// However, in this simple case, `ref(HomeView)` works fine as we're just storing the reference.
// Using string names and a component map: (if you wanted to use strings instead of component objects directly)
/*
const currentTab = ref('Home');
const tabs = {
Home: HomeView,
About: AboutView,
Contact: ContactView
};
const currentComponent = computed(() => tabs[currentTab.value]);
*/
</script>
<style scoped>
nav button {
margin-right: 10px;
padding: 8px 15px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #f9f9f9;
cursor: pointer;
}
nav button:hover {
background-color: #e9e9e9;
}
.component-container {
margin-top: 20px;
padding: 20px;
border: 1px solid #eee;
border-radius: 5px;
min-height: 150px;
}
</style>
How it works: This snippet illustrates how to use dynamic components in Vue 3 with the special `<component :is="activeComponent" />` attribute. This allows you to render different components based on a reactive value (`activeComponent` in this case). When the value of `activeComponent` changes, Vue intelligently swaps out the current component for the new one. This pattern is incredibly useful for building interfaces with tabs, wizards, or highly configurable sections. The `KeepAlive` wrapper is included to optionally preserve the state of inactive dynamic components, preventing them from being unmounted and re-mounted every time you switch.