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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs