2017-11-18 4 views
0

私は複数のフィールドを持つテーブル行を持つコンポーネントを持っています。 によって1つのフィールドを更新すると、マージンまたは販売価格に基づいて別のフィールドが更新されます。VueJsウォッチャーを動的に管理する

しかし、私はすべてのフィールドを見ているように、私はバウンス効果を得ています。 _debounceを追加すると問題は解決しますが、問題は解決しません。この問題を解決するには、ウォッチャーにコールバックを使用してunwatch()をトリガーしますが、ウォッチャーを再追加すると、コールバックが見えなくなります。

私はコードの例として作業要点を持っています。

view example gist

Vue.component('pricing', { 

    template: '#pricing-row', 

    props: ['item'], 

    mounted() { 
    this.addWatchers() 
    }, 

    methods: { 

     resetWatchers() { 
     setTimeout(()=> { 
      this.addWatchers() 
     }, 700) 
    }, 

    addWatchers() { 

     this.updateNet = this.$watch(
     function() { 
      return this.item.net 
     }, 
     function() { 
      // unmount other watchers 
      this.updateMargin() 
      this.updateSell() 
      // calculate sell price and update 
      this.setSellPrice() 
      // re-add watchers 
      this.resetWatchers() 
     } 
    ), 

     this.updateMargin = this.$watch(
     function() { 
      return this.item.margin 
     }, 
     function() { 
      // unmount other watchers which can cause bounce effect 
      this.updateSell() 
      // calculate sell price and update 
      this.setSellPrice() 
      // re-add watchers 
      this.resetWatchers() 
     } 
    ), 

     this.updateSell = this.$watch(
     function() { 
      return this.item.sell 
     }, 
     function(sellPrice) { 
      // unmount other watchers which can cause bounce effect 
      this.updateMargin() 
      // update margin 
      this.setMargin(sellPrice) 
      // re-add watchers 
      this.resetWatchers() 
     } 
    ) 
    }, 

    setSellPrice() { 
     let price = (100/(100 - this.item.margin)) * this.item.net 
     this.item.sell = price.toFixed(2) 
    }, 

    setMargin(sellPrice) { 
     let profit = (sellPrice - this.item.net) 
     let price = (100 * profit)/sellPrice 
     this.item.margin = price.toFixed(2) 
    } 
    } 

}) 

new Vue({ 
    el: '#vue', 
    data: { 
    prices: [ 
     { 
     id: 1, 
     net: 5, 
     margin: 10, 
     sell: 5.56 
     }, 
     { 
     id: 2, 
     net: 7, 
     margin: 10, 
     sell: 7.78 
     },  
    ] 
    } 
}) 

私はメソッドを呼び出すmounted()上に取り付けることにより、正しくウォッチャーを使用しています信じています。そしてその方法を思い出して再初期化するか?

本当にお役に立てれば幸いです。

+0

をこの問題のより複雑なバージョンを見ることができ、これは非常に不幸なソリューションです。 'net'、' margin'と 'sell'属性の間の関係だけを記述できますか? – WaldemarIce

+0

基本的には、売却価格を更新することにより、ネットとマージンに基づいて売却価格を自動的に再計算します。他のフィールドについても同様です。 – Lee

+0

これは無限ループです。今、私は問題がどこにあるのか理解しています...単純な解決策は、 '売却 'プロパティを原価として考えています。直接使用することはできません。また、実質売価として、ネット、マージン、原価に基づいて計算されたプロパティを使用する必要があります。 – WaldemarIce

答えて

0

は、ここでは計算された値によって抽象化されている(ネット、マージン、販売)計算値

各パラメータを使用したソリューションです。 getterはthis.item値を返し、setterはthis.item値を更新してから関連する値を更新します。

これは、カラーピッカーと同様の問題であり、あなたがここにhttp://jsfiddle.net/Phunky/2enc99r1/

Vue.component('pricing', { 
 
\t template: '#pricing-row', 
 
    props: ['item'], 
 
    computed: { 
 
    \t net:{ 
 
    \t get() { 
 
     \t return Number(this.item.net) 
 
     }, 
 
     set (net) { 
 
     \t this.item.net = Number(net) 
 
     this.setSellPrice() 
 
     } 
 
    }, 
 
    \t margin:{ 
 
    \t get() { 
 
     \t return this.item.margin 
 
     }, 
 
     set (margin) { 
 
     \t this.item.margin = Number(margin) 
 
     this.setSellPrice() 
 
     } 
 
    }, 
 
    \t sell:{ 
 
    \t get() { 
 
     \t return this.item.sell 
 
     }, 
 
     set (sell) { 
 
     \t this.item.sell = Number(sell) 
 
     \t this.setMargin() 
 
     } 
 
    } 
 
    }, 
 
    methods: { 
 
    
 
    setSellPrice() { 
 
     let price = (100/(100 - this.margin)) * this.net 
 
     this.item.sell = price.toFixed(2) 
 
    }, 
 
    
 
    setMargin() { 
 
     let profit = (this.sell - this.net) 
 
     let price = (100 * profit)/this.sell 
 
     this.item.margin = Number(price.toFixed(2)) 
 
    } 
 
    } 
 
    
 
}) 
 

 
new Vue({ 
 
    el: '#vue', 
 
    data: { 
 
    \t prices: [ 
 
    \t { 
 
     \t id: 1, 
 
     net: 5, 
 
     margin: 10, 
 
     sell: 5.56 
 
     }, 
 
    \t { 
 
     \t id: 2, 
 
     net: 7, 
 
     margin: 10, 
 
     sell: 7.78 
 
     },  
 
    ] 
 
    } 
 
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.5/vue.min.js"></script> 
 
<script type="text/x-template" id="pricing-row"> 
 
    <tr> 
 
    \t <td><input v-model="net" /></td> 
 
    <td><input v-model="margin" /></td> 
 
    <td><input v-model="sell" /></td> 
 
    </tr> \t 
 
</script> 
 

 

 
<div id="vue"> 
 
    <table> 
 
    <tr> 
 
     <th>Net</th> 
 
     <th>Margin</th> 
 
     <th>Price</th> 
 
    </tr> 
 
    <tr is="pricing" v-for="(price, index) in prices" :item="price" :key="price.id"></tr> 
 
    </table> 
 
</div>

+0

に投稿します。私は同じことをしました。しかし、私はまだバウンス効果を得ています。スクリーンキャストを参照してください。 http://d.pr/i/1l04rR – Lee

+0

このような時間の不満の後、私はルートの原因を見つけました。私はbootstrap-vueを使用しています。入力にも発砲しているようです。私は銃! TY – Lee

+0

私はこれらのライブラリを使用することを避けようとしています。これはhttps://picturepan2.github.io/spectre/のようなCSS専用のフレームワークよりも優先されます。あるいは、追加された機能が必要な場合は、elemnet.io vue、およびvueのポートやマテリアルやブートストラップのようなパッチは適用されません。 – Daniel

関連する問題