23

While building a Vue application we re-use certain Vue components in every template. Our grid system exists out of .region, .layout, .grid, .column elements. All of them are separate Vue components (, ...).

We now end up doing this in every template:

import BlMain from '~components/frame/main/Main.vue'
import BlRegion from '~components/frame/region/Region.vue'
import BlLayout from '~components/frame/layout/Layout.vue'
import BlGrid from '~components/frame/grid/Grid.vue'
import BlColumn from '~components/frame/column/Column.vue'

Is there a way to import Vue Components globally in your project? Is it an option to create a component Frame.vue that contains the imports above and add the Frame component in every template? How do other FE frameworks tackle this?

We are using Nuxt JS upon Vue.

Warre Buysse
  • 1,335
  • 4
  • 21
  • 39
  • 2
    The most common way I've seen is you can create a file that exports all of them and then you can reduce the imports to one file like this: http://stackoverflow.com/a/29722646 – Christopher Mar 27 '17 at 07:54
  • I understand how it works with ES6 classes, yet I can't seem to get it working with Vue components.. – Warre Buysse Mar 27 '17 at 08:32

5 Answers5

58

You should use a plugin that registers the account.

// plugins/bl-components.js

import Vue from 'vue'
import BlMain from '~components/frame/main/Main.vue'
import BlRegion from '~components/frame/region/Region.vue'
import BlLayout from '~components/frame/layout/Layout.vue'
import BlGrid from '~components/frame/grid/Grid.vue'
import BlColumn from '~components/frame/column/Column.vue'
    
const components = { BlMain, BlRegion, ... }
   
Object.entries(components).forEach(([name, component]) => {
    Vue.component(name, component)
})
// nuxt.config.js

export default {
    plugins: ['~plugins/bl-components']
}
solidau
  • 4,021
  • 3
  • 24
  • 45
motia
  • 1,939
  • 16
  • 22
  • 1
    There is a WARNING note in nuxt documentation related to this way of component registration, that it will cause memory leaking on the server side as mentioned here: https://nuxtjs.org/docs/directory-structure/plugins/#inject-in-root--context – Abdulrahman Hashem Oct 23 '21 at 09:51
  • @AbdulrahmanHashem The note says `Don't use Vue.component() inside the function exported by your plugin.` which is not the case in the code snippet above so it shouldn't create a memory leak. – pmrotule Oct 26 '22 at 10:27
7

!!! Always name your components starting with Base, for example: BaseIcon.vue
1. First, you need to create a plugin in your plugin folder, I called mine global.js
2. Install lodash: npm install lodash
3. Inside global.js add this code:

import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'

const requireComponent = require.context(
  '~/components',
  false,
  /Base[A-Z]\w+\.(vue|js)$/
)

requireComponent.keys().forEach((fileName) => {
  const componentConfig = requireComponent(fileName)

  const componentName = upperFirst(
    camelCase(fileName.replace(/^\.\/(.*)\.\w+$/, '$1'))
  )

  Vue.component(componentName, componentConfig.default || componentConfig)
})

  1. Inside your nuxt.config.js add plugins: ['@plugins/global.js']
  2. Now you can use your base components only by typing <BaseIcon />
Tircomnicu
  • 79
  • 1
  • 2
3

In your nuxt.config.js, set components to true.

https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-components

Raza
  • 3,147
  • 2
  • 31
  • 35
  • 4
    This will only save you the typing. The components will still be imported each time and additionally your build, and therefore hot reload times, will increase dramatically. I recently had to disable this feature and manually import all components because dev hmr times become unbearable. It just isn't worth it. – George Marios Feb 15 '21 at 11:26
3

You can do this by creating custom plugin something like this..

import Vue from 'vue'

/** form */
import Email from '~/components/elements/form/Email'
import Mobile from '~/components/elements/form/Mobile.vue'
import Password from '~/components/elements/form/Password'
import TextInput from '~/components/elements/form/TextInput.vue'
import FormLayout from '~/components/elements/form/FormLayout.vue'
import SelectInput from '~/components/elements/form/SelectInput.vue'
import ConfirmPassword from '~/components/elements/form/ConfirmPassword'

/** snackbar */
import Snackbar from '~/components/elements/Snackbar.vue'

/** skeleton */
import PageListing from '~/components/skeleton/PageListing'

/** slots */
import OneRow from '~/components/slots/layouts/OneRow'
import LoginWrapper from '~/components/slots/layouts/LoginWrapper'

/** slots tab */
import TabHolder from '~/components/slots/layouts/TabHolder'
import TabHolderHeading from '~/components/slots/layouts/TabHolderHeading.vue'

/** gallery */
import GalleryInput from '~/components/gallery/GalleryInput.vue'
import GalleryDialog from '~/components/gallery/GalleryDialog.vue'

const components = { TabHolderHeading, TabHolder, GalleryInput, GalleryDialog, Snackbar, LoginWrapper, PageListing, OneRow, Password, FormLayout, ConfirmPassword, Email, Mobile, TextInput, SelectInput }

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

Now make it available globally by calling it in nuxt.config.js

plugins: [
    { src: '~/plugins/import-design-elements' }
],
Pushkar Raj
  • 193
  • 3
  • 7
1

Make a frame.vue under the folder layout , import all your components in it and make it the layout for all your templates, like /template.vue