Vue.js - Making helper functions globally available to single-file components

I have a Vue 2 project that has many (50+) single-file components. I use Vue-Router for routing and Vuex for state.

There is a file, called helpers.js, that contains a bunch of general-purpose functions, such as capitalizing the first letter of a string. This file looks like this:

export default {
  capitalizeFirstLetter(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }
}

My main.js file initializes the app:

import Vue from 'vue'
import VueResource from "vue-resource"
import store from "./store"
import Router from "./router"
import App from "./components/App.vue"

Vue.use(VueResource)

const app = new Vue({
  router: Router,
  store,
  template: '<app></app>',
  components: { App },
}).$mount('#app')

My App.vue file contains the template:

<template>
  <navbar></navbar>
  <div class="container">
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // stuff
    }
  }
}
</script>

I then have a bunch of single-file components, which Vue-Router handles navigating to inside the <router-view> tag in the App.vue template.

Now let's say that I need to use the capitalizeFirstLetter() function inside a component that is defined in SomeComponent.vue. In order to do this, I first need to import it:

<template>Some Component</template>

<script>
import {capitalizeFirstLetter} from '../helpers.js'
export default {
  data() {
    return {
      myString = "test"
    }
  },
  created() {
    var newString = this.capitalizeFirstLetter(this.myString)
  }
}
</script>

This becomes a problem quickly because I end up importing the function into many different components, if not all of them. This seems repetitive and also makes the project harder to maintain. For example if I want to rename helpers.js, or the functions inside it, I then need to go into every single component that imports it and modify the import statement.

Long story short: how do I make the functions inside helpers.js globally available so that I can call them inside any component without having to first import them and then prepend this to the function name? I basically want to be able to do this:

<script>
export default {
  data() {
    return {
      myString = "test"
    }
  },
  created() {
    var newString = capitalizeFirstLetter(this.myString)
  }
}
</script>

Solution 1:

inside any component without having to first import them and then prepend this to the function name

What you described is mixin.

Vue.mixin({
  methods: {
    capitalizeFirstLetter: str => str.charAt(0).toUpperCase() + str.slice(1);
  }
})

This is a global mixin. with this ALL your components will have a capitalizeFirstLetter method, so you can call this.capitalizeFirstLetter(...) from component methods or you can call it directly as capitalizeFirstLetter(...) in component template.

Working example: http://codepen.io/CodinCat/pen/LWRVGQ?editors=1010

See the documentation here: https://vuejs.org/v2/guide/mixins.html

Solution 2:

Otherwise, you could try to make your helpers function a plugin:

import Vue from 'vue'
import helpers from './helpers'

const plugin = {
  install () {
    Vue.helpers = helpers
    Vue.prototype.$helpers = helpers
  }
}

Vue.use(plugin)

In your helper.js export your functions, this way:

const capFirstLetter = (val) => val.charAt(0).toUpperCase() + val.slice(1);
const img2xUrl = (val) => `${val.replace(/(\.[\w\d_-]+)$/i, '@2x$1')} 2x`;

export default { capFirstLetter, img2xUrl };

or

export default { 
  capFirstLetter(val) {
    return val.charAt(0).toUpperCase() + val.slice(1);
  },
  img2xUrl(val) {
    return `${val.replace(/(\.[\w\d_-]+)$/i, '@2x$1')} 2x`;
  },
};

You should then be able to use them anywhere in your components using:

this.$helpers.capitalizeFirstLetter()

or anywhere in your application using:

Vue.helpers.capitalizeFirstLetter()

You can learn more about this in the documentation: https://vuejs.org/v2/guide/plugins.html