How to dynamically import multiple Vue.js components at once? - vue.js

I'm trying to import multiple components from a folder conditionally. The first example works, but I need to get it working conditionally like in the last example that doesn't work. Otherwise I'd have to always go and change which components should import manually, after adding one to the project folder.
I've also tried wrapping the imports into a function, but I can't get the import * as components syntax to work. Importing one component works fine, but not with * return () => import * as components '#/components/index'
This works
import * as components from '#/components/index'
export default {
components: {
...loadedComponents
}
}
index.js and electronIndex.js
export {
default as one
}
from './One.vue'
export {
default as two
}
from './Two.vue'
This of course doesn't work, but demonstrates what I need
I also tried importing conditionally via functions like stated above, but can't get that to work either.
const IPC = window.ipcRenderer
if (IPC) {
import * as components from '#/components/electronIndex'
} else {
import * as components from '#/components/index'
}
export default {
components: {
...loadedComponents
}
}

Related

How to watch deep state change in component using pinia

I'm having problems with watching deep changes inside component. My store looks like this (simplified):
import {defineStore} from 'pinia'
import {PiniaAuth} from "#/store/piniaauth";
import {get, getDatabase, ref, set, update} from "firebase/database";
import {toRaw} from 'vue'
import {PiniaMainStore} from "#/store/pinia";
// useStore could be anything like useUser, useCart
// the first argument is a unique id of the store across your application
export const PiniaInfo = defineStore('info', {
// arrow function recommended for full type inference
state: () => {
return {
info: {
name: 'John',
bill: 10000,
}
}
},
}
I need to watch bill changes and recount other data in component run methods. I've seen the function storeToRefs but didn't find how to watch if the data is in another object (in my case inside the info object).
Are there any ways to do this?

Vue 3 use dynamic component with dynamic imports

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?
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

How to import multiple vue files as one

In other to avoid multiple imports into my vuejs app I created an index.js file and imported all the files in it like so:
import AddMember from "./AddMember.vue";
import EditMember from "./EditMember.vue";
export {
AddMember,
EditMember,
};
Then in my component compenent I imported them like so:
import * as Members from "../members/index.js";
export default {
name: "members-table",
components: {
AddMember: Members.AddMember
EditMember: Members.EditMember,
},
}
The EditMember Component is a dialog that opens up per the member clicked. But Anytime I click on a member on a the table I get and error that looks like this: even though the name prop was defined in all the components.
Unknown custom element: <edit-member> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I resolved the problem my importing the EditMember.vue file itselfimport EditMember from './EditMember';. My question however, is there a way I can achieve this. Or better still what I'm I missing or did wrong.
well if it`s reusable components your trying to do so wouldnt it be better to create base components? and then you dont need to import them each time?
import { AddMember, EditMember } from "../members/index.js"; this should work like #Asimple said
Maybe you can try to import them separately?
Like this:
import { AddMember, EditMember } from "../members";
Update:
Changed import source, please, try it.
Working example here
Try this, you may need to create alias as:
components: {
'AddMember': Members.AddMember, // use single quotes
'EditMember': Members.EditMember,
},

Vue.js how to load dependent components

Vue.js : how to load dependent components?
From router currently using component as follows:
import A from './A';
export default {
components : {
'new-comp-A' : NewCompA
}
}
...
But this renders the template before import causing errors. Is there a better way for loading dependencies?
The template uses the - did you register the component correctly.
Your casing is incorrect. Use either 'NewCompA' or 'new-comp-a' for the name.
In fact, it would be even easier to use
import NewCompA from 'wherever/the/component/is/defined'
export default {
components: {
NewCompA
}
}
Your template can then use either
<NewCompA></NewCompA>
<!-- or -->
<new-comp-a></new-comp-a>
See https://v2.vuejs.org/v2/guide/components-registration.html#Name-Casing
After looking at your code again, it does not seem normal. You are assigning the variable A to your component, but trying to import it with the variable NewCompA..
You need to change the following:
From this:
import A from './A';
export default {
components : {
'new-comp-A' : NewCompA
}
}
...
To this:
import A from './A';
export default {
components : {
'NewCompA' : A
}
}
...
and use it like this:
<new-comp-a>

Vue Component Import

I know this question has been asked several times, unfortunately i can't figure it out. My question is how to import all vue single file components from a directory in one shot. Le'me clear that..
Say i have directory named as Add/Items where i stored all vue components, ItemA, ItemB and so on. I want to import these components to a Add.vue file which is sitting just outside the Add directory.
I have tried these methods (in Add.vue file script section) ..
Method #1:
import ItemA from './Add/Items/ItemA'
import ItemB from './Add/Items/ItemB'
export default {
components: {
'item-a': ItemA,
'item-b': ItemB
}
}
and it works, with <item-a/> as well as with <component is="item-a"/>
but the following method does not work.
Method #2
Here i have created a file named index.js at Add/Items directory where the following snippet is written
import itemA from './ItemA'
import ItemB from './ItemB'
export default {
ItemA,
ItemB
}
and in the Add.vue file
import items from './Add/Items'
export default {
components: {
items
}
}
And it is working neither with <item-a/> nor with <component is="item-a"/>.
Is there something i m missing ?? and by the way, <component :is="item-a"/> is my preference.
Thanks in advance.
In last example(Add.vue) in your question you will get this(that is not what you want):
components: {
items: {
ItemA,
ItemB
}
}
You just need to use spread(...) operator or assign items to components directly:
export default {
components: {
...items
}
}
OR this:
export default {
components: items
}