如何在Vue.js中的组件之间共享方法?

Mik*_*ike 32 javascript vue.js

看看这个简单的购物车演示:

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)
}
Run Code Online (Sandbox Code Playgroud)

我该怎么做才能改变这种方法并将其全局使用?我正在使用这个项目的Vue路由器,感谢您的帮助!

cod*_*ion 39

我发现这种技术更简单/更令人满意,因为我更喜欢组合而不是继承:

SRC/shared.js

export default {
  foo: function() { alert("foo!") }
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

这也将允许您编写与Vue无关的测试.

注意:如果你需要FOO在Vue公司范围的运行替换this.foo = shared.foothis.foo = shared.foo.bind(this)

  • 我认为它应该是```import from'./ shared'```而没有共享的引号 (2认同)
  • 为了在模板中使用它,您可以将函数添加到您的方法中,例如“export default { name: 'componentName',methods: { shared, } }” (2认同)

Pet*_*ter 37

选项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)
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

您可以在每个组件中引用它,如下所示:

var Vegetable = Vue.extend({
    template: '#vegetable',
    mixins: [cartMixin],
    data: function(){
        return sourceOfTruth
    }
})
Run Code Online (Sandbox Code Playgroud)

...然后在你的模板中使用它,如下所示:

<li v-for="product in food | showOnly 'fruit'" @click="selectProduct(product)">
  {{product.name}}
</li>
Run Code Online (Sandbox Code Playgroud)

这是你的Plunker的一个分支.

选项2

思考这个多一些之后,你可能会考虑另一种选择是创建一个基础Product组件和扩展来创建FruitVegetable组件.然后,您可以将常用功能放在基本组件中.

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',
});
Run Code Online (Sandbox Code Playgroud)

这是采用这种方法的Plunker.

鉴于您的水果和蔬菜模板非常相似,您可以进一步采用这个想法并使用基础组件中的通用模板.

  • 我认为选项 1 是这里最“正确”的 vue 答案……尽管在我看来,Mixins 的名字很不明确。也许应该称为AddIns、AddOns、Extenders、ShareMes等。 (2认同)

Jef*_*eff 2

您可以将该方法放入根 Vue 实例中,然后在选择蔬菜或选择水果时从子实例分派一个事件。事件在其父组件上查找处理程序,如果找不到事件处理程序,它们将继续沿着链向上查找,直到找到为止。所以在你的根实例上:

events: {
    'choose-fruit':function(fruit){

        //handle the choosing of fruit

    }
}
Run Code Online (Sandbox Code Playgroud)

然后在子实例上:

selectFruit: function(product){

    this.$dispatch('choose-fruit', product);

}
Run Code Online (Sandbox Code Playgroud)