JAVASCRIPT
Dynamically Render Components Based on Data in Vue 3
Efficiently render different components dynamically based on data, enhancing flexibility and modularity in your Vue 3 application's UI.
// components/HomeComponent.vue
<template>
<div class="card">
<h3>Home Section</h3>
<p>Welcome to the dashboard!</p>
<button @click="$emit('navigate', 'Profile')">Go to Profile</button>
</div>
</template>
<script setup>
defineEmits(['navigate']);
</script>
<style scoped> .card { border: 1px solid #eee; padding: 20px; border-radius: 8px; margin-bottom: 15px; background-color: #f9f9f9; } </style>
// components/ProfileComponent.vue
<template>
<div class="card">
<h3>User Profile</h3>
<p>Name: {{ userName }}</p>
<p>Email: {{ userEmail }}</p>
<button @click="$emit('navigate', 'Settings')">Go to Settings</button>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
defineProps(['userName', 'userEmail']);
defineEmits(['navigate']);
</script>
<style scoped> .card { border: 1px solid #eee; padding: 20px; border-radius: 8px; margin-bottom: 15px; background-color: #f9f9f9; } </style>
// components/SettingsComponent.vue
<template>
<div class="card">
<h3>Settings</h3>
<p>Adjust your preferences here.</p>
<button @click="$emit('navigate', 'Home')">Go to Home</button>
</div>
</template>
<script setup>
defineEmits(['navigate']);
</script>
<style scoped> .card { border: 1px solid #eee; padding: 20px; border-radius: 8px; margin-bottom: 15px; background-color: #f9f9f9; } </style>
// App.vue
<template>
<div id="app">
<h1>Dynamic Component Example</h1>
<nav>
<button @click="currentComponent = 'HomeComponent'">Home</button>
<button @click="currentComponent = 'ProfileComponent'">Profile</button>
<button @click="currentComponent = 'SettingsComponent'">Settings</button>
</nav>
<keep-alive>
<component
:is="components[currentComponent]"
@navigate="currentComponent = $event"
:user-name="currentUser.name"
:user-email="currentUser.email"
></component>
</keep-alive>
</div>
</template>
<script setup>
import { ref, markRaw } from 'vue';
import HomeComponent from './components/HomeComponent.vue';
import ProfileComponent from './components/ProfileComponent.vue';
import SettingsComponent from './components/SettingsComponent.vue';
const currentComponent = ref('HomeComponent');
const currentUser = ref({ name: 'Jane Doe', email: '[email protected]' });
// A map to store components for dynamic rendering
const components = {
HomeComponent: markRaw(HomeComponent),
ProfileComponent: markRaw(ProfileComponent),
SettingsComponent: markRaw(SettingsComponent)
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
nav button {
margin: 0 5px;
padding: 10px 15px;
cursor: pointer;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #e0e0e0;
}
nav button:hover {
background-color: #d0d0d0;
}
</style>
How it works: This snippet demonstrates how to dynamically render different components in Vue 3 using the `<component :is="...">` element. `App.vue` imports several child components and defines a `currentComponent` ref that holds the name of the component to display. The `<component :is="components[currentComponent]">` then renders the corresponding component from the `components` object. Props (`userName`, `userEmail`) are passed to the dynamic component, and emitted events (`navigate`) are handled to update `currentComponent`, enabling seamless navigation between views. `keep-alive` is used to preserve the state of inactive components. `markRaw` is used to prevent the components object from being deeply reactive, which is a performance optimization when the components themselves don't need to be reactive.