Как я могу поделиться методом между компонентами в Vue.js?
Ознакомьтесь с этой простой демо-версией корзины покупок:
http://plnkr.co/edit/CHt2iNSRJAJ6OWs7xmiP?p=preview
Пользователь может выбрать veggie и фрукты, и он будет добавлен в корзину. Функция, которая добавляет фрукты /veggie, очень похожа, и я хочу объединить ее в функцию, которая может быть разделена между обоими компонентами.
selectFruit: function(product){
var cart = this.cart
for(p in cart){
if (cart[p]["type"] == "fruit"){
console.log("We already got a fruit!, Let remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.name
var cartFruit = {name: product.name, type: 'fruit'}
this.cart.push(cartFruit)
}
selectVeggie: function(product){
var cart = this.cart
for(p in cart){
if (cart[p]["type"] == "veggie"){
console.log("We already got a veggie!, Let remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.name
var cartVeggie = {name: product.name, type: 'veggie'}
this.cart.push(cartVeggie)
}
Как я могу это сделать, чтобы изменить этот метод и использовать его во всем мире? Я использую Vue Router с этим проектом, спасибо за любую помощь!
Ответы
Ответ 1
Я нашел эту технику более простой/удовлетворительной, так как я предпочитаю композицию, а не наследование:
SRC/shared.js
export default {
foo: function() { alert("foo!") }
}
SRC/yourcomponent.vue
<template>...</template>
<script>
import shared from './shared'
export default {
created() {
this.foo = shared.foo // now you can call this.foo() (in your functions/template)
}
}
</script>
Это также позволит вам писать Vue-независимые тесты.
ПРИМЕЧАНИЕ: если вам нужно, чтобы foo работал в Vue-scope, замените this.foo = shared.foo
на this.foo = shared.foo.bind(this)
Ответ 2
Вариант 1
Один из способов совместного использования вашего метода между компонентами - использовать mixin. Здесь a cartMixin
, который содержит метод selectProduct
:
var cartMixin = {
methods: {
selectProduct: function (product) {
var cart = this.cart
for(p in cart){
if (cart[p]["type"] == product.type){
console.log("We already got a "+ product.type +"!, Let remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.name
var cartProduct = {name: product.name, type: product.type}
this.cart.push(cartProduct)
}
}
};
Вы можете ссылаться на это в каждом компоненте следующим образом:
var Vegetable = Vue.extend({
template: '#vegetable',
mixins: [cartMixin],
data: function(){
return sourceOfTruth
}
})
... и затем используйте его в своих шаблонах следующим образом:
<li v-for="product in food | showOnly 'fruit'" @click="selectProduct(product)">
{{product.name}}
</li>
Здесь вилка вашего плункера.
Вариант 2
Подумав об этом, еще один вариант, который вы можете рассмотреть, - создать базовый компонент Product
и расширить его, чтобы создать компоненты Fruit
и Vegetable
. Затем вы поместите свою общую функциональность в базовый компонент.
var Product = Vue.extend({
data: function(){
return sourceOfTruth
},
methods: {
selectProduct: function (product) {
var cart = this.cart
for(p in cart){
if (cart[p]["type"] == product.type){
console.log("We already got a "+ product.type +"!, Let remove " + cart[p]["name"] + " and add in " + product["name"]);
this.cart.$remove(cart[p])
}
}
console.log("Adding " + product.name + " to cart.");
var productName = product.name
var cartProduct = {name: product.name, type: product.type}
this.cart.push(cartProduct)
}
}
})
var Vegetable = Product.extend({
template: '#vegetable',
});
var Fruit = Product.extend({
template: '#fruit',
});
Здесь Plunker с таким подходом.
Учитывая, что ваши шаблоны Fruit and Vegetable настолько похожи, вы могли бы принять эту идею еще дальше и использовать общий шаблон из базового компонента.
Ответ 3
Вы можете поместить этот метод в свой корневой экземпляр Vue, а затем отправить событие из дочернего экземпляра, когда выбран veggie или когда выбран фрукт. События ищут обработчик на их родительском компоненте, и если они не находят обработчик событий, они продолжают подниматься по цепочке до тех пор, пока они не сделают это. Итак, в корневом экземпляре:
events: {
'choose-fruit':function(fruit){
//handle the choosing of fruit
}
}
Затем на дочернем экземпляре:
selectFruit: function(product){
this.$dispatch('choose-fruit', product);
}