簡體   English   中英

如何在 Vue.js 中的組件之間共享方法?

[英]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 路由器,感謝您的幫助!

我發現這種技術更簡單/令人滿意,因為我更喜歡組合而不是繼承:

源代碼/共享.js

export default {
  foo: function() { alert("foo!") }
}

源代碼/你的組件.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 范圍內運行,請將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>

這是你的 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',
});

這是采用這種方法的 Plunker

鑒於您的水果和蔬菜模板非常相似,您或許可以進一步擴展這個想法並使用基本組件中的通用模板。

如果您嘗試在多個 vue 模板和布局之間或沿共享相同的組件邏輯,您可以簡單地嘗試以下這種方法:

前:

一個.vue

<template>
  <div>
     <h1>{{title}}</h1>
     <small>{{datetime}}</small>
  </div>
</template>

<script>
export default {
  props: {
    title: String
  },
  data() {
    return {
      datetime: new Date()
    }
  }
}
</script>

b.vue

<template>
  <div>
     <h3>{{title}}</h3>
     <h6>{{datetime}}</h6>
  </div>
</template>

<script>
export default {
  props: {
    title: String
  },
  data() {
    return {
      datetime: new Date()
    }
  }
}
</script>

后:

一個.vue

<template>
  <div>
     <h1>{{title}}</h1>
     <small>{{datetime}}</small>
  </div>
</template>

<script>
import shared from "./shared.js";
export default Object.assign({}, shared);
</script>

b.vue

<template>
  <div>
     <h3>{{title}}</h3>
     <h6>{{datetime}}</h6>
  </div>
</template>

<script>
import shared from "./shared.js";
export default Object.assign({}, shared);
</script>

共享.js

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM