Vue/Nuxt: How to make a component be truly dynamic?

Marc picture Marc · Sep 24, 2019 · Viewed 8.6k times · Source

In order to use a dynamically-defined single page component, we use the component tag, thusly:

<component v-bind:is="componentName" :prop="someProperty"/>

...

import DynamicComponent from '@/components/DynamicComponent.vue';

...
components: {
    DynamicComponent
},

props: {
    componentName: String,
    someProperty: null,
}

The problem is, this isn't really very dynamic at all, since every component we could ever possibly want to use here needs to be not only imported statically, but also registered in components.

We tried doing this, in order at least to avoid the need to import everything:

created() {
    import(`@/components/${this.componentName}.vue`);
},

but of course this fails, as it seems that DynamicComponent must be defined before reaching created().

How can we use a component that is truly dynamic, i.e. imported and registered at runtime, given only its name?

Answer

James Coyle picture James Coyle · Sep 24, 2019

From the documentation: Emphasis mine

<!-- Component changes when currentTabComponent changes -->
<component v-bind:is="currentTabComponent"></component> 

In the example above, currentTabComponent can contain either:

  • the name of a registered component,
  • or a component’s options object

If currentTabComponent is a data property of your component you can simply import the component definition and directly pass it to the component tag without having to define it on the current template.

Here is an example where the component content will change if you click on the Vue logo.

Like this:

<component :is="dynamic" />

...

setComponentName() {
    this.dynamic = () => import(`@/components/${this.componentName}.vue`);
},