动态管理VueJs Watchers

时间:2017-11-18 19:07:45

标签: javascript vue.js vuejs2 vue-component

我有一个带有表格行的组件,其中我有多个字段。通过 更新一个字段将使用基于保证金或卖出价格的值更新另一个字段。

但是当我正在观察所有领域时,我会得到一个弹跳效果。添加_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()调用方法安装在观察者身上来正确使用观察者。通过回忆那种方法重新初始化?

我真的希望你能提供帮助。

1 个答案:

答案 0 :(得分:0)

这是使用计算值的解决方案

每个参数(净值,保证金,卖出价)都是通过计算值抽象出来的。 getter返回this.item值,setter首先更新this.item值,然后更新相关值。

这与颜色选择器类似,您可以在此处查看此问题的更复杂版本http://jsfiddle.net/Phunky/2enc99r1/

Vue.component('pricing', {
	template: '#pricing-row',
  props: ['item'],
  computed: {
  	net:{
    	get () {
      	return Number(this.item.net)
      },
      set (net) {
      	this.item.net = Number(net)
        this.setSellPrice()
      }
    },
  	margin:{
    	get () {
      	return this.item.margin
      },
      set (margin) {
      	this.item.margin = Number(margin)
        this.setSellPrice()
      }
    },
  	sell:{
    	get () {
      	return this.item.sell
      },
      set (sell) {
      	this.item.sell = Number(sell)
      	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: {
  	prices: [
    	{ 
      	id: 1,
        net: 5,
        margin: 10,
        sell: 5.56
      },
    	{ 
      	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>
  	<td><input v-model="net" /></td>
    <td><input v-model="margin"  /></td>
    <td><input v-model="sell"  /></td>
  </tr>	
</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>