[英]How can I share a method between components in Vue.js?
看看这个简单的购物车演示:
http://plnkr.co/edit/CHt2iNSRJAJ6OWs7xmiP?p=preview
用户可以选择蔬菜和水果,并将其添加到购物车数组中。 添加水果/蔬菜的 function 非常相似,我想将它组合成一个可以在两个组件之间共享的 function。
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 路由器,感谢您的帮助!
我发现这种技术更简单/令人满意,因为我更喜欢组合而不是继承:
export default {
foo: function() { alert("foo!") }
}
<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 范围内运行,请将
this.foo = shared.foo
替换为this.foo = shared.foo.bind(this)
选项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',
});
鉴于您的水果和蔬菜模板非常相似,您或许可以进一步扩展这个想法并使用基本组件中的通用模板。
如果您尝试在多个 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()
}
}
}
您可以将该方法放在根 Vue 实例中,然后在选择蔬菜或选择水果时从子实例调度事件。 事件在它们的父组件上寻找一个处理程序,如果它们没有找到一个事件处理程序,它们就会一直向上移动直到找到为止。 所以在你的根实例上:
events: {
'choose-fruit':function(fruit){
//handle the choosing of fruit
}
}
然后在子实例上:
selectFruit: function(product){
this.$dispatch('choose-fruit', product);
}
我只会配置一个mixin
export const sharedMethods = {
// Generic funcion
methods: {
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);
},
}
然后在组件中使用 mixin,像调用组件本身的函数一样调用它的函数,就好像这些函数是你正在导入 mixin 的组件的一部分:
放到组件上: mixins: [sharedMethods],
在组件内部,我调用了 mixin 函数:
this.axiosPost(
'/route',
data,
() => console.log('success'),
() => console.log('fail')
)
这很有用,因为使用一种方法,您只需从 js 文件中导入函数,被导入的文件中的函数将使用它们自己的“this”在可能会引起一些混乱的函数中使用,而 mixin 将使用“this”正如我所说的,它被导入的组件的一部分,就好像它的功能是组件的一部分。
注意:如果您在共享文件 utils.js 中有 2 个(或更多)方法,您可以使用以下方法从另一个方法调用一个方法:
实用程序.js:
export default {
method1(){
···
return ...
},
method2(){
val1 = this.method1();
···
return ...
},
}
你的组件.vue
<template>...</template>
<script>
import utils from './utils.js';
export default {
created() {
val2 = utils.method2();
}
}
</script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.