4

I use Vue 3 and I have a dynamic component. It takes a prop called componentName so I can send any component to it. It works, kind of.

Part of the template

<component :is="componentName" />

The problem is that I still need to import all the possible components. If I send About as a componentName I need to import About.vue.

Part of the script

I import all the possible components that can be added into componentName. With 30 possible components, it will be a long list.

import About "@/components/About.vue";
import Projects from "@/components/Projects.vue";

Question

It there a way to dynamically import the component used?

Boussadjra Brahim
  • 82,684
  • 19
  • 144
  • 164
Jens Törnell
  • 23,180
  • 45
  • 124
  • 206

1 Answers1

4

I already faced the same situation in my template when I tried to make a demo of my icons which are more than 1k icon components so I used something like this :

import {defineAsyncComponent,defineComponent} from "vue";

const requireContext = require.context(
    "@/components", //path to components folder which are resolved automatically
    true,
    /\.vue$/i,
    "sync"
);
let componentNames= requireContext
    .keys()
    .map((file) => file.replace(/(^.\/)|(\.vue$)/g, ""));

let components= {};

componentNames.forEach((component) => { //component represents the component name
    components[component] = defineAsyncComponent(() => //import each component dynamically
        import("@/components/components/" + component + ".vue")
    );
});
export default defineComponent({
    name: "App",
    data() {
        return {
            componentNames,// you need this if you want to loop through the component names in template
         
        };
    },
    components,//ES6 shorthand of components:components or components:{...components }

});

learn more about require.context

xlm
  • 6,854
  • 14
  • 53
  • 55
Boussadjra Brahim
  • 82,684
  • 19
  • 144
  • 164
  • 1
    If you have trouble resolving "require.context", you may need to import @types/webpack-env and change your tsconfig to include those types: https://github.com/rails/webpacker/issues/1276 – Robert Mar 21 '21 at 14:04
  • FYI the line `import("@/components/components/" + component + ".vue")` cause Webpack to load all modules that match the pattern. See also https://stackoverflow.com/a/42804941/885922 and https://webpack.js.org/api/module-methods/#dynamic-expressions-in-import – xlm Sep 22 '21 at 11:39