Vue.js:错误设置计算属性

时间:2016-10-26 14:04:15

标签: vue.js

在下面的代码中(jsbin available here)我有两个输入元素,一个范围和一个文本,通过计算属性绑定在一起。

var vm = new Vue({
  el: '#main-container',
  data: {
    sliderValue: 100,
  },
  computed: {
    actualValue: {
      get: function() {
        if (this.sliderValue <= 100) {
          return this.sliderValue;
        } else {
          return Math.round(this.sliderValue * 12.5 - 1150);
        }
      },
      /* set won't work for val > 100*/
      set: function(val) {
        if (val <= 100) {
          this.sliderValue = val;
        } else {
          this.sliderValue = Math.round((val + 1150)/12.5);
        }
      }
    }
  },
  methods: {
    
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
    <div id="main-container">
      <input type="range" v-model="sliderValue" min=1 max=132>
      <input type="text" v-model="actualValue">
      <p>Slider: {{sliderValue}}</p>
      <p>Actual: {{actualValue}}</p>
    </div>

范围从1到132,其范围在文本输入中被映射[1..500],具有简单的变换(基本上它是具有两个不同斜率的线性映射[ 1..100]和[101..132])使用 actualValue 计算属性。

获取actualValue按预期工作:正确拖动滑块会使用[1..500]范围内的适当值更新输入文本。

但是,我无法找到设置actualValue的方法。我希望能够在文本输入中键入一个值,并使滑块的拇指相应地更改为逆变换(val + 1150)/12.5。

只要输入的数字在[1..100]范围内,它就可以工作,但对于数字> 100,它会“爆炸”,例如101使sliderValue跳转到80892,然后将actualValue重新计算为1010000.据我所知,这是一个循环反馈场景。

我也尝试了其他方法(观看; v-on:改变文本输入;使用第三个变量)无济于事。

提前感谢任何建议!

2 个答案:

答案 0 :(得分:2)

这是一个了不起的谜题,并且长时间地挑战了我!

请看下面的截图。您的sliderValue和actualValue是字符串,而不是整数。将actualValue设置为101时,实际上是将其设置为字符串值"101"

enter image description here

现在,您的sliderValue = ((actualValue + 1150)/12.5)

"101" + 1150 = "1011150"(另一个字符串!,在开发者控制台中试用)

这会弄乱你的整个计算。现在你知道如何解决它: - )

你需要从这里获得Vue devtools:https://github.com/vuejs/vue-devtools

编辑:回复评论#3

以下是经过修改的jsBin:http://jsbin.com/mahejozeye/1/edit?html,js,output

唯一的区别是在console.log函数中引入了两个map2语句。这有助于您确定您的非线性映射功能是否正常工作。如果您打开开发人员控制台,您将看到此功能正在发生的事情。

  • 案例1:当您使用文本框设置值radius = 25时,sliderRadius设置为111.55518394648828并再次重新计算radius25。所以它绕了整整一圈,一切都很稳定。

  • 案例2:当您设置值radius = 55时,您的sliderRadius会通过非线性 map2()功能设置为173.03607214428857 ,将半径重置为51.29869180420927

显然存在循环依赖问题。您的sliderRadiusradius非常依赖彼此,因此radius无法取得51到58之间的值。

您需要评估它发生的原因,因为它与您定义的非线性映射函数有很大关系。 radius时刻可以在55处获得稳定值(通过map2函数),然后您当前的问题将得到解决。

enter image description here

答案 1 :(得分:1)

最简单的解决方法是将输入类型设置为number

<input type="number" v-model="actualValue">

或者您可以将您的值转换为类似的整数:

  set: function(val) {
    var intVal = parseInt(val, 10);

    if (!isNaN(intVal)) {
      if (intVal <= 100) {
        this.sliderValue = Math.max(1, intVal);
      } else {
        this.sliderValue = Math.min(132, Math.round((intVal + 1150) / 12.5));
      }
    }
  }