在下面的代码中(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:改变文本输入;使用第三个变量)无济于事。
提前感谢任何建议!
答案 0 :(得分:2)
这是一个了不起的谜题,并且长时间地挑战了我!
请看下面的截图。您的sliderValue和actualValue是字符串,而不是整数。将actualValue
设置为101
时,实际上是将其设置为字符串值"101"
现在,您的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
并再次重新计算radius
为25
。所以它绕了整整一圈,一切都很稳定。
案例2:当您设置值radius = 55
时,您的sliderRadius
会通过非线性 map2()功能设置为173.03607214428857
,将半径重置为51.29869180420927
显然存在循环依赖问题。您的sliderRadius
和radius
非常依赖彼此,因此radius
无法取得51到58之间的值。
您需要评估它发生的原因,因为它与您定义的非线性映射函数有很大关系。 radius
时刻可以在55处获得稳定值(通过map2函数),然后您当前的问题将得到解决。
答案 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));
}
}
}