Meena Chaudhary
Meena Chaudhary

Reputation: 10715

Where to put VueJS components common across the application

In my nuxtjs application, I have few features that are used across the application viz Login/Signup dialog, a snackbar to show alerts etc. Since, I want these features on every page and v-app-bar component is already added to all the pages. I have included the components for these features inside v-app-bar component.

<template>
  <v-app-bar app id="app-bar">
    <LoginJoinDialog />
    <AlertSnackbar />

    <!-- Code for App bar -->

  </v-app-bar>
</template>

But I am not happy with this approach for following reasons

  1. I know these common components does not belong to the v-app-bar component. And just for the sake of DRY and maintenance headaches I have included them. So from design perspective this is not very intuitive.
  2. Secondly, What if in future I have pages that do not have a v-app-bar component. In that case I will be repeating code for these common components anyway. So, the pain of maintaining the code at multiple places will still be there.

Considering the above points, I am looking for a more elegant approach than what I have implemented. If there is a vuejs recommendation on this, even better. What suggestions do you have for component structuring for these common features?

Upvotes: 1

Views: 544

Answers (2)

htmn
htmn

Reputation: 1675

You can use global component registration trick by Chris Fritz. You just to need to modify it a bit so it's more fitting for a nuxt.js app. So you can create a base folder under your components folder and keep all these shared components there. Then create a new plugin and change the path to your @/components/base folder and modify the regex so it grabs all the files, no matter what the name is:

globalComponents.js

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

export default () => {
  const requireComponent = require.context(
    '@/components/base', false, /[\w-]+\.vue$/
  )

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

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

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

nuxt.config.js

plugins: [
  '~/plugins/globalComponents.js'
],

Upvotes: 0

Vectrobyte
Vectrobyte

Reputation: 1485

You can acheive what you are looking for using layouts. What you need to do is make layouts folder inside src directory. And then you can create as many layout components(*.vue files) and use them as you like.

For an example, this is default.vue component inside layouts folder:

<template>
  <main>
    <!-- Your app bar component -->
    <v-app-bar app id="app-bar">
      <LoginJoinDialog />
      <AlertSnackbar />
      <!-- Code for App bar -->
    </v-app-bar>

    <!-- Page Content (This tag will automatically embed the page content into layouts)-->
    <nuxt />

  </main>
</template>

<script>
export default {};
</script>

Now, on your pages folder, you can add index.vue file where you can reference the default layout, as a property in this manner: layout: 'default'

The index.vue file should look something like this:

<template>
  <!-- page content goes here -->
</template>

<script>
export default {
  name: 'HomePage',
  layout: 'default',
};
</script>

I also have created an example project in nuxt with layouts.

For a working prototype of the project: Visit this link.

I hope it helps to solve your issue.

Upvotes: 1

Related Questions