Vuex - Sharing common functions across modules

13,022

Solution 1

The simplest case is, naturally, to just define a regular function in a js file and import/use it anywhere you need it.

There are Vue-specific approaches, though:

For common reusable functions in Vuex modules, you can use Vuex Plugins.

Check an example below. Mind the usage at the root store: plugins: [myTruncatePlugin].

const myTruncatePlugin = store => {
  store.truncate = function(str) {
    return str.replace(/-/g, '') + ' ...was truncaaaated!'; // example implementation
  }
}

const moduleA = {
  namespaced: true,
  state: {name: "name@moduleA"},
  mutations: { changeName(state, data) { state.name = this.truncate(data); } },
}
const moduleB = {
  namespaced: true,
  state: {title: "title@moduleB"},
  mutations: { changeTitle(state, data) { state.title = this.truncate(data); } },
}
const myStore = new Vuex.Store({
  strict: true,
  modules: {
    aaa: moduleA,
    bbb: moduleB
  },
  plugins: [myTruncatePlugin]  // IMPORTANT: YOU MUST DECLARE IT HERE
});
new Vue({
  store: myStore,
  el: '#app',
  mounted: function() {
    setTimeout(() => {
      this.changeName("-n-e-w-N-A-M-E-");
      this.changeTitle("-n-e-w-T-I-T-L-E-");
    }, 200);
  },
  computed: {
    ...Vuex.mapState('aaa', ['name']),
    ...Vuex.mapState('bbb', ['title'])
  },
  methods: {
    ...Vuex.mapMutations('aaa', ['changeName']),
    ...Vuex.mapMutations('bbb', ['changeTitle'])
  }
})
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>

<div id="app">
  <p>moduleA's name: {{ name }}</p>
  <p>moduleB's title: {{ title }}</p>
</div>

For common reusable functions in Vue instances, you can use Mixins. For the most general case there's the Global Mixin (use with care):

Vue.mixin({
  methods: {
    truncate(str) {
      return str.replace(/-/g, '') + ' ...was truncaaaated!'; // example implementation
    }
  }
})

// this.truncate() will be available in all Vue instances...
new Vue({
  el: '#app1',
  data: {myStr1: '-o-n-e-'},
  mounted() { this.myStr1 = this.truncate(this.myStr1); }
})
new Vue({
  el: '#app2',
  data: {myStr2: '-t-w-o-'},
  mounted() { this.myStr2 = this.truncate(this.myStr2); }
})
// ...and components
Vue.component('my-comp', {
template: '#t3',
  data() { return {myStr3: '-t-h-r-e-e-'} },
  mounted() { this.myStr3 = this.truncate(this.myStr3); }
});
new Vue({
  el: '#app3',
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>

<div id="app1">App1: "{{ myStr1 }}"</div>
<div id="app2">App2: "{{ myStr2 }}"</div>

<template id="t3">
  <div>App3's component: "{{ myStr3 }}"</div>
</template>
<div id="app3"><my-comp></my-comp></div>

Solution 2

@acdcjunior has the best answer using Mixins, but I'm giving you another option by just declaring method in your Vue instance.

So belows example, I am creating doTruncate method in Vue instance then the components are calling them by this.$parent.doTruncate

// register
Vue.component('cart-component', {
  template: '<button @click="doTruncate">Cart Truncate!</button>',
  methods: {
  	doTruncate: function() {
    	this.$parent.doTruncate("Hello from cart");
    }
  }
})

// register
Vue.component('customer-component', {
  template: '<button @click="doTruncate">Customer Truncate!</button>',
  methods: {
  	doTruncate: function() {
    	this.$parent.doTruncate("Hello from customer");
    }
  }
})

var app3 = new Vue({
  el: '#app',
  methods: {
  	doTruncate: function(params) {
    	alert(params);
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
<cart-component></cart-component>
<br>
<customer-component></customer-component>
<br>
<button @click="doTruncate('Hello from parent')">
Parent!
</button>
</div>
Share:
13,022

Related videos on Youtube

Vishwas
Author by

Vishwas

Updated on June 04, 2022

Comments

  • Vishwas
    Vishwas almost 2 years

    I am working on a Vue Js 2 application and I'm currently building the store and the different modules to separate out the code. Is there a way to write a common function and share it across all modules?

    For example, I have a function truncate() that I need to be use in customer.js, cart.js, address.js. If I declare it in store.js and try to use in modules, it throws an error. Is export and import the only way? What is the best way to share the function?