I'm trying to implement a way to display components on demand by means of dynamic components and lazy load.
However when it comes to dynamically importing the component file, I get this error:
Error: Cannot find module '@/components/pages/UsersPage.vue' at eval (eval at ./src/components/multiwindows lazy recursive
This is the component called Multiwindows (a cut short version), in which I try to load the selected component:
<template>
<component :is="getComponent()"></component>
</template>
<script>
export default {
props: ['window'],
methods: {
getComponent(window) {
const path = `@/components/pages/${this.window.component}.vue`;
return import(path);
}
}
}
</script>
window is an object passed as a prop including the data needed for the selected component. An example of it would be (note the component property which is the one taking place in the code above):
{
name: 'Users',
class: 'far fa-user',
component: 'UsersPage',
}
The file structure of my project is like this:
- src
- components
- multiwindows
- MultiWindows.vue
- pages
- UsersPage.vue
- multiwindows
- components
I can't get to asynchronously import UsersPage.vue, and it doesn't matter if I change the path constant to a relative path, which since I'm importing from MultiWindows, should be like this:
const path = `../pages/${window.component}.vue`;
or if I try with an absolute path, both starting with / or not:
const path = `/src/components/pages/${window.component}.vue`;
EDIT:
I also noticed these errors in console:
sockjs.js?9be2:1687 WebSocket connection to 'wss://mydomain/sockjs-node/919/1qzk04x2/websocket' failed:
sockjs.bundle.js:1 Uncaught Error: Incompatible SockJS! Main site uses: "1.5.2", the iframe: "1.5.0".
Chances are these errors are related to the module not being imported, but I don't know how to fix them. I explicitly installed the sockjs-client package with NPM in case it was due to an outdated version. No success.
CodePudding user response:
I tested a solution for using dynamic component and lazy load them in Vue-js version 2. I'm not sure that it works for version 3. I used computed properties instead of Vue methods. Here is my index page code that passes the data to containerCompo component (the corresponding Multiwindows component in the question):
<template>
<div class="about">
<v-container
class="px-0"
fluid
>
<v-row>
<v-col md="12">
<container-compo :window1="compoData">
</container-compo>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
import containerCompo from "../components/containerCompo";
export default {
data () {
return {
compoData: {
name: 'Users',
class: 'far fa-user',
component1: 'dynamic1', // the name of dynamic component
}
}
},
components: {
containerCompo,
}
}
</script>
<style scoped>
</style>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
the containerCompo has "window1" prop that accepts the data include the component name. Here is the code of containerCompo component:
<template>
<section>
<component v-if="isCompoVisible" :is="getComponent"></component>
<v-btn @click="isCompoVisible= true">click me</v-btn>
</section>
</template>
<script>
export default {
name: 'containerCompo',
data () {
return {
isCompoVisible: false,
}
},
props: ["window1"],
computed: {
getComponent() {
let data = this.window1.component1;
return () => import(`./${data}`);
}
}
}
</script>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
The getComponent computed data processes the window1 prop and extract the dynamic component name to be used in vue <component>
tag. I supposed that containerCompo.vue
and all dynamic components are in the same level in components folder of Vue and index.vue is in the views folder.
CodePudding user response:
This is not the complete solution but it may help you
You need to register a component before using it
and there is also a method to dynamically import components defineAsyncComponent
import app from '@/main';
import { defineAsyncComponent } from 'vue';
....
// Check if the component has already been registered.
if (!app._context.components[componentName]) {
app.component(
componentName,
defineAsyncComponent(() => import(`@/components/pages/${componentName}.vue`)),
);
}