Dynamic components is a Vue.js feature that enables users to dynamically render different components based on certain conditions or user interactions. These components allow users to switch between two or more components —in other words, dynamically mount and unmount components in the UI — without using routing. Dynamic components also maintain the data state when returning to the initial component.
When designing your user interface, you’ll want some form of flexibility to show or hide nested components based on the application state. Dynamic components provide that platform in an efficient and simple way.
The feature saves you from a lot of code since you can easily achieve dynamic components with Vue conditional structures such as v-if and v-else. You can use conditional structures to achieve dynamic components by using a placeholder approach to easily bind logic to the component.
This approach will ensure that your presentation is always clean and unambiguous.
To follow along with the examples in this article, you’ll need the following:
node -v
If you don’t have a Vue.js project set up, you can scaffold a new one with the following command:
npm init vue@latest
This command will initiate create-vue, the official Vue project scaffolding tool. It will prompt you to select some configurations; you can use the image below as a guide:

Once the installation is complete, run the following commands to install the project’s peer dependencies and start the development server:
cd vue-project npm install npm run dev
Vue offers a special inbuilt component, called component, that accepts a :is directive, specifying the name or definition of the component to be rendered. Here’s an example:
<component :is=”currentComponent”></component>
The component can also be a self-closing tag:
<component :is=”currentComponent”/>
N.B., for the sake of compatibility with different browsers, the first option is the most suitable
In the above example, the component will render whatever component is specified by the currentComponent data property. You can change this property dynamically, and the component will re-render with the new component.
In order to showcase the functionality of the <component/>, we’ll generate two dynamic components and switch between them without using routing. To accomplish this, go to your project’s components directory and create two new components. Name them Test_1 and Test_2 and insert the following code into each component, respectively:
<template>
//use "Test 2" for the second component
<div><h1>Test 1</h1>
</div>
</template>
<script>
export default {
name: 'Test_1',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
Now that you have the components set up, go to the App.vue file and register the components, like so:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<Test_1 />
<Test_2 />
</div>
</template>
<script>
import Test_1 from './components/Test1.vue'
import Test_2 from './components/Test2.vue'
export default {
name: 'app',
components: {
Test_1, Test_2
}
}
</script>
<style scoped>
#App {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
</style>
If you save the code at this point and open the browser, you should see a page similar to this:

As you can see, both components are simultaneously being rendered to the browser. If you want to mount only one component and then dynamically switch to the other, you have to create a dynamic component.
To do this, return to the App.vue component and replace the Test component declarations with the <component/> :
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<component />
</div>
</template>
Next, you’ll need to declare a variable that corresponds with your current rendering component:
export default {
name: "app",
components: {
Test_1,
Test_2,
},
data() {
return {
component: "Test_1",
};
},
};
</script>
In the code above, we default to the Test_1 component by passing its name as a string value to the component variable.
Finally, pass the component variable to the :is directive on the <component/> to dynamically render the default component, which in this case is the Test_1 component:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<component:is="component" />
</div>
</template>
Upon saving the code, you’ll notice that only the Test_1 component is displayed on the browser.

Currently, we are unable to switch between the components. We need a way to toggle the value of the component variable from Test_1 to Test_2. To accomplish this, we will generate two buttons that, when clicked, will mount their corresponding components.
<button @click="component ='Test_1'">Test_1</button> <button @click="component ='Test_2'">Test_2</button>
When you add these buttons to the template in App.vue, and return to the browser, you should be able to dynamically switch both components as depicted in the GIF below:

As the Vue team built this feature, they opted to extend its capabilities to include storing data values per state.
To store this data, Vue provides a template element called keep-alive. Using keep-alive, you can ensure your component state stays exactly as you left it after you switch back from one component to the other.
For example, if you click on a link or enter a value in a text box and then switch components, keep-alive brings you back to the same link or text box you were using when you switch back.
To enable keep-alive, go to the template section of your app.vue file and wrap the component element with the keep-alive element:
<keep-alive> <component :is="component" /> </keep-alive>
To see if it works, add a form and two radio elements to your Test_1.vue and Test_2.vue components, respectively:
//Test1
<template>
<div><h1>Test 1</h1>
<form>
First name:<br>
<input type="text" name="firstname"><br>
Last name:<br>
<input type="text" name="lastname">
</form>
</div>
</template>
//Test2
<template>
<div><h1>Test 2</h1>
<div>
<label for="test">One</label>
<input type="radio" name="test" id="test" />
<label for="test">two</label>
<input type="radio" name="test" id="test" />
</div>
</div>
</template>
When you save all project files, run the application again. Type into the input boxes, switch components, and toggle back to the original component. You’ll notice the values you typed before switching components are exactly as you left them.

In the absence of the <keep-alive> component, the default behavior of dynamic components will be as follows:

In this article, we provided an introduction to using dynamic components in your Vue.js workflow. You also now have the ability to extend the powers of the component element through keep-alive.
This is a great tool for building user interfaces and can be applied to a variety of different use cases. Happy hacking!
Debugging Vue.js applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Vue mutations and actions for all of your users in production, try LogRocket.

LogRocket lets you replay user sessions, eliminating guesswork by showing exactly what users experienced. It captures console logs, errors, network requests, and pixel-perfect DOM recordings — compatible with all frameworks.
With Galileo AI, you can instantly identify and explain user struggles with automated monitoring of your entire product experience.
Modernize how you debug your Vue apps — start monitoring for free.

Large hosted LLMs aren’t always an option. Learn how to build agentic AI with small, local models that preserve privacy and scale.

What storylines defined 2025 in frontend development? We power rank them all, from AI advancements to supply chain attacks and framework breakthroughs.

Learn how to style React Native apps with Tailwind using NativeWind v4.

A practical guide to the best React Native UI libraries in 2026, with comparisons across performance, theming, accessibility, and Expo compatibility.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up now
5 Replies to "Making your components dynamic in Vue 3"
Excellent article, thank you. I build backend APIs and want to venture into frontend builds. This article will help me dynamically load API data per component.
Also, nice touch in discussing . Thanks again!
You say it’s dynamic but the imports are hard coded? How do I get dynamic imports with these components. I’ve been searching the internet for days. 🙁
Finally a clear explanation to help me to solve my problems, thank you for that!
May i know how to remove the error no-unused-components from eslint when using dynamic components?
Really nice explanation. But example with binding via “is” not working when it is not a dynamic.
is=”Test1″ must be :”Test1″ otherwhise VUE/ESLINTER wrote something about error and that it must be in this style.
Its about settings or Vue version or what? Thx 🙂
Otherwise perfectly simple 🙂