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?
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?
Share Improve this question asked Mar 15, 2018 at 4:00 VishwasVishwas 1,4988 gold badges22 silver badges34 bronze badges3 Answers
Reset to default 12The 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>
@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>
you can use vue js events to share function like
eventBus.js // it will create common instance
import Vue from 'vue';
export const eventBus = new Vue();
common.js // your common functions will go into this file
import { eventBus } from '<path of file>';
mounted() {
eventBus.$on('truncate',()=> {
this.truncate();
})
}
methods: {
truncate(){
//truncate code
}
}
customer.js // call your common truncate function from customer.js
import { eventBus } from '<path of file>';
eventBus.$emit('truncate');