Vue.js:设置计算 属性 时出错

Vue.js: error setting a computed property

在以下代码 (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] 范围内,它就可以工作,但它 "explodes" 对于 >100 的数字,例如101 使 sliderValue 跳到 80892,然后 actualValue 被重新计算为 1010000。据我了解,这是一个循环反馈场景。

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

提前感谢您的任何建议!

这是一个神奇的谜题,挑战了我很长时间!

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

的字符串值

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

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

这会打乱你的整个计算。现在您知道如何修复它了:-)

你需要从这里获取 Vue 开发工具:https://github.com/vuejs/vue-devtools

编辑:对评论 #3 的回应

这里是修改后的jsBin:http://jsbin.com/mahejozeye/1/edit?html,js,output

唯一的区别是在 map2 函数中引入了两个 console.log 语句。这有助于您确定非线性映射函数是否正常工作。如果你让你的开发者控制台保持打开状态,你会看到这个函数发生了什么。

  • 情况 1:当您使用文本框设置值 radius = 25 时,您的 sliderRadius 被设置为 111.55518394648828 并且您的 radius 再次设置重新计算为 25。所以它绕了一圈,这里一切都很稳定。

  • 情况 2:当您设置值 radius = 55 时,您的 sliderRadius 通过非线性 map2( ) 函数,它将半径重置为 51.29869180420927

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

你需要评估它为什么会发生,因为它与你定义的非线性映射函数有很大关系。一旦radius可以稳定取值55(通过map2函数),那么你现在的问题就解决了。

最简单的解决方法是将输入类型设置为 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));
      }
    }
  }