查看这个简单的购物车演示:
http://plnkr.co/edit/CHt2iNSRJAJ6OWs7xmiP?p=preview
用户可以选择素食和水果,它将被添加到购物车阵列中。添加水果/蔬菜的功能非常相似,我想将它组合成一个可以在两个组件之间共享的功能。
selectFruit: function(product){
var cart = this.cart
for(p in cart){
if (cart[p]["type"] == "fruit"){
console.log("We already got a fruit!, 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.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'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.name
var cartVeggie = {name: product.name, type: 'veggie'}
this.cart.push(cartVeggie)
}
我该如何制作,以便我可以改变这种方法并将其全局使用?我正在使用这个项目的Vue路由器,感谢您的帮助!
答案 0 :(得分:31)
我发现这种技术更简单/更令人满意,因为我更喜欢构图而不是继承:
export default {
foo: function() { alert("foo!") }
}
<template>...</template>
<script>
import shared from './shared'
export default {
mounted: function() {
this.foo = shared.foo // now you can call this.foo() (in your functions/template)
}
}
</script>
这也允许您编写与Vue无关的测试。
注意:如果您需要foo在Vue范围内运行,请将
this.foo = shared.foo
替换为this.foo = shared.foo.bind(this)
答案 1 :(得分:28)
选项1
跨组件共享方法的一种方法是使用mixin。这是一个包含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'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.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'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.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',
});
Here's a Plunker with this approach
鉴于您的水果和蔬菜模板非常相似,您可以进一步采用这个想法并使用基础组件中的通用模板。
答案 2 :(得分:2)
您可以将方法放在根Vue实例中,然后在选择素食时或选择水果时从子实例调度事件。事件在其父组件上寻找处理程序,如果他们找不到事件处理程序,他们就会继续向上行,直到他们这样做。所以在你的根实例上:
events: {
'choose-fruit':function(fruit){
//handle the choosing of fruit
}
}
然后在子实例上:
selectFruit: function(product){
this.$dispatch('choose-fruit', product);
}
答案 3 :(得分:1)
如果您试图在多个vue模板和布局之间或沿多个vue模板和布局共享相同的组件逻辑,则可以在下面简单地尝试这种方法:
之前:
<template>
<div>
<h1>{{title}}</h1>
<small>{{datetime}}</small>
</div>
</template>
<script>
export default {
props: {
title: String
},
data() {
return {
datetime: new Date()
}
}
}
</script>
<template>
<div>
<h3>{{title}}</h3>
<h6>{{datetime}}</h6>
</div>
</template>
<script>
export default {
props: {
title: String
},
data() {
return {
datetime: new Date()
}
}
}
</script>
之后:
<template>
<div>
<h1>{{title}}</h1>
<small>{{datetime}}</small>
</div>
</template>
<script>
import shared from "./shared.js";
export default Object.assign({}, shared);
</script>
<template>
<div>
<h3>{{title}}</h3>
<h6>{{datetime}}</h6>
</div>
</template>
<script>
import shared from "./shared.js";
export default Object.assign({}, shared);
</script>
export default {
props: {
title: String
},
data() {
return {
datetime: new Date()
}
}
}