33
votes

I have a vue app that I created using the vue-cli

Im creating some components and I want to use them like this:

<template>
    <oi-list>
        <oi-list-header>Task ID</oi-list-header>
        <oi-list-header>Tasks Title</oi-list-header> 
        <oi-list-header>Task Status</oi-list-header> 
        <div v-for="task in tasks">
            <oi-list-item>{{ task.id }}</oi-list-item>
            <oi-list-item>{{ task.title }}</oi-list-item>
            <oi-list-item>{{ task.status }}</oi-list-item>
        </div>
    </oi-list>
</tempalte>

The probelm I have is where ever I use the list component I have to write the following:

<script>
    import List from '@/components/List'
    import ListHeader from '@/components/ListHeader'
    import ListItem from '@/components/ListItem'

    export default {
    name: "Tasks",
    components: {
        'oi-list': List,
        'oi-list-header': ListHeader,
        'oi-list-item': ListItem
    }
<script>

What I would like is for reusable components to either be registered globally so i dont have to import them and their sub components every time i want to use them, or some how have them load dynamically when I use them. Is this possible?

I have used Vuetify in the past and that doesn't require you to import each component in order to use it.

Please can someone point me in the right direction? Thanks.

7
Thanks Ayush - ill give this a go - Brad

7 Answers

0
votes

You can recursivly go through your files and import them by their component name or file name.

 const files = require.context('./', true, /\.vue$/i)

 files.keys().map(key => {
     Vue.component(files(key).default.name ?? key.split('/').pop().split('.')[0], files(key).default);
 })

70
votes

This is easy to accomplish. You can register components globally in the main.js file.

import MyComponent from '@/components/MyComponent'

Vue.component('my-component-name', MyComponent)

Now you can use <my-component-name /> everywhere.

A cleaner way, without bloating your main.js, is to import your component in an index.js file in your components folder like this.

import Vue from 'vue'
import MyComponent from '@/components/MyComponent'

Vue.component('my-component-name', MyComponent)

Later you can add this line to your main.js to load the registered components.

import '@/components'

the docs: https://vuejs.org/v2/guide/components-registration.html

18
votes

As another option in addition to @Odyssee's answer, if you want to avoid globals, is to create a file, say globalComponents.js with the following contents:

import List from '@/components/List.vue'
import ListHeader from '@/components/ListHeader.vue'
import ListItem from '@/components/ListItem.vue'
export default {
    'oi-list': List,
    'oi-list-header': ListHeader,
    'oi-list-item': ListItem
}

And you can use it as follows:

<script>
    import GlobalComponents from '@/globalComponents.js'

    export default {
    name: "Tasks",
    components: {
        ...GlobalComponents
    }
<script>
6
votes

A combination of multiple solutions which i believe is the cleanest approach:

global-components.js:

import Vue from 'vue'

const components = {
  'comp1':   () => import('components/comp1'),
  'comp2': () => import('components/comp2'),
}

Object.entries(components).forEach(([name, component]) => Vue.component(name, component))

main.js:

import 'global-components'
4
votes

Even simpler you may import global components like so:

In your main.js. (Note Vue.component() must be called before new Vue())

Vue.component(
  'MyComponent', () => import('./components/MyComponent')
)
2
votes

If anyone is looking to do so using TypeScript, it can be done by chaining it with the createApp() method as

import { createApp } from "vue";
import App from "./App.vue";

import GlobalComponent from "./components/GlobalComponent.vue";

createApp(App)
    .component("global-component", GlobalComponent)
    .mount("#app");
1
votes

You dont have to repeat the component name, if it is the same name as the import. So this is enough:

import FirstComponent from '@/components/FirstComponent'
import SecondComponent from '@/components/SecondComponent'

const components = {
  FirstComponent,
  SecondComponent
}
Object.entries(components).forEach(([name, component]) => Vue.component(name, component))