动态管理 VueJs 观察者



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

但是当我观察所有领域时,我得到了反弹效果。添加_debounce有帮助,但不会解决问题。为了尝试管理问题,我正在使用对观察者的回调来触发 unwatch((,但是当我重新添加观察者时,回调停止取消监视。

我有一个工作要点作为代码示例。

查看示例要点

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()调用方法来正确使用观察程序。并通过调用该方法重新初始化?

我真的希望你能帮忙。

下面是使用计算值的解决方案

每个参数(净值、保证金、卖出(都通过计算值进行抽象。getter 返回 this.item 值,资源库器首先更新 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>

最新更新