How Can I Share A Method Between Components In Vue.js?
Solution 1:
I found this technique to be more simple/satisfactory, as I prefer composition over inheritance:
src/shared.js
exportdefault {
foo: function() { alert("foo!") }
}
src/yourcomponent.vue
<template>...</template><script>import shared from'./shared'exportdefault {
created() {
this.foo = shared.foo// now you can call this.foo() (in your functions/template)
}
}
</script>
This will also allow you to write Vue-agnostic tests.
NOTE: if you need foo to run in Vue-scope replace
this.foo = shared.foo
withthis.foo = shared.foo.bind(this)
Solution 2:
Option 1
One approach for sharing your method across components is to use a mixin. Here's a cartMixin
that contains a selectProduct
method:
var cartMixin = {
methods: {
selectProduct: function (product) {
var cart = this.cartfor(p in cart){
if (cart[p]["type"] == product.type){
console.log("We already got a "+ product.type +"!, Let's remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.namevar cartProduct = {name: product.name, type: product.type}
this.cart.push(cartProduct)
}
}
};
You can reference this in each component like this:
varVegetable = Vue.extend({
template: '#vegetable',
mixins: [cartMixin],
data: function(){
return sourceOfTruth
}
})
... and then use it in your templates like this:
<liv-for="product in food | showOnly 'fruit'" @click="selectProduct(product)">
{{product.name}}
</li>
Here's a fork of your Plunker.
Option 2
After thinking about this some more, another option you might consider is to create a base Product
component and extend that to create your Fruit
and Vegetable
components. You would then put your common functionality in the base component.
varProduct = Vue.extend({
data: function(){
return sourceOfTruth
},
methods: {
selectProduct: function (product) {
var cart = this.cartfor(p in cart){
if (cart[p]["type"] == product.type){
console.log("We already got a "+ product.type +"!, Let's remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.namevar cartProduct = {name: product.name, type: product.type}
this.cart.push(cartProduct)
}
}
})
varVegetable = Product.extend({
template: '#vegetable',
});
varFruit = Product.extend({
template: '#fruit',
});
Here's a Plunker with this approach.
Given that your Fruit and Vegetable templates are so similar, you might be able to take this idea even further and use a common template from the base component.
Solution 3:
If you are trying to share the same component logic between or along multiple vue template and layout, you can simply try this approach below:
before:
a.vue
<template><div><h1>{{title}}</h1><small>{{datetime}}</small></div></template><script>exportdefault {
props: {
title: String
},
data() {
return {
datetime: newDate()
}
}
}
</script>
b.vue
<template><div><h3>{{title}}</h3><h6>{{datetime}}</h6></div></template><script>exportdefault {
props: {
title: String
},
data() {
return {
datetime: newDate()
}
}
}
</script>
after:
a.vue
<template><div><h1>{{title}}</h1><small>{{datetime}}</small></div></template><script>import shared from"./shared.js";
exportdefaultObject.assign({}, shared);
</script>
b.vue
<template><div><h3>{{title}}</h3><h6>{{datetime}}</h6></div></template><script>import shared from"./shared.js";
exportdefaultObject.assign({}, shared);
</script>
shared.js
exportdefault {
props: {
title: String
},
data() {
return {
datetime: newDate()
}
}
}
Solution 4:
You can put the method in your root Vue instance and then dispatch an event from the child instance when a veggie is selected, or when a fruit is selected. Events look for a handler on their parent component, and if they don't find an event handler they keep going up the chain until they do. So on your root instance:
events: {
'choose-fruit':function(fruit){
//handle the choosing of fruit
}
}
Then on the child instance:
selectFruit: function(product){
this.$dispatch('choose-fruit', product);
}
Solution 5:
I would just configure a mixin
exportconst sharedMethods = {
// Generic funcionmethods: {
axiosGet(route){
return axios.get(route)
.then(response => response.data)
.catch((error)=> {console.log(error)})
},
axiosPost(route, postObj, resolveCallback, rejectCallback){
axios.post(route, postObj)
.then(resolveCallback)
.catch(rejectCallback);
},
}
And then use the mixin in the component, calling its functions as you would do with the functions of the component itself, as if the functions were part of the component you are importing the mixin in:
Put it on the component: mixins: [sharedMethods],
Inside the component, I call the mixin function:
this.axiosPost(
'/route',
data,
() =>console.log('success'),
() =>console.log('fail')
)
It is useful because using an aproach where you just import functions from a js file, the functions in the file being imported will take their own 'this' to use in the functions which might cause some confusion, whereas mixin will use the 'this' of the component it is being imported in, as if its functions were part of the component, as I said.
Post a Comment for "How Can I Share A Method Between Components In Vue.js?"