我从服务器的json响应中获得ViewModel中的一个String。它看起来像这样:
"manual_setpoint": "200",
然后我需要在我的视图中显示它:
<div class="setpoint" data-bind="text: vm.manual_setpoint(), style: { color: vm.state()? '#f00000' : '#777777'}"></div>
它需要显示为数字20(200/10(,因为有按钮可以增加和减少可观察到的值(例如201->20.1199->19.9(。这不是问题,因为我的可观察到在本地定义为数字。我是这样做的:
self.manual_setpoint.formatted = function() {
return (self.manual_setpoint() / 10);
};
然后在我的视图中显示manual_setup.formated((。我也有增加和减少这种可观察到的按钮,如下所示:
self.decSetpoint = function (observable) {
decrement(observable);
};
var decrement = function (observable) {
observable(observable() - 1);
};
现在,当服务器的响应是String时,我的方法就不再工作了。(例如,对于200+1,我得到2001等…(
如何以最简单优雅的方式处理这种情况?我需要在我的视图中显示正确的数字(所以对于200,我需要20(,我必须能够递增和递减与之前相同的可观测值
继续@johndoe的评论-恕我直言,我不同意。如果我误解了这个问题,很乐意删除答案。
如果该值在JSON中作为字符串发送,并通过ko.map.fromJs进行映射,那么它很有可能被映射为ko.observable("200")
而不是ko.observable(200)
- 做一些关于映射的事情,将值转换为整数/浮点值,这将使
decrement()
函数按预期工作;或 -
更改递减函数以转换值,如下所示。
var decrement = function (observable) { observable(parseInt(observable()) - 1); };
我也会更改
self.manual_setpoint.formatted = function() {
return (self.manual_setpoint() / 10);
};
至
self.manual_setpoint.formatted = ko.pureComputed(function() {
return (self.manual_setpoint() / 10);
});
这样,当manual_settit被更改时,格式化的版本也会被更新。
编辑
好吧,我纠正了需要为格式化函数使用pureComputed的问题。使用这个基本测试,似乎只需使用一个函数就可以按预期工作。很长一段时间以来,我一直认为,添加一个以某种方式包装可观察对象的函数会执行一次,如果在包装函数执行后(通常在绑定过程中(更新了包装的可观察对象,则不会更新。因此,当视图绑定到包装函数时,视图将不会更新,因为返回的函数是不可观察的。
此外,根据测试,parseInt似乎也不是真正需要的,可能是因为函数正在进行除法。我认为我的经验是基于添加,这会导致类似"20" + 1 = "201"
而不是20 + 1 = 21
的
希望下面的测试能像帮助我一样帮助你。
var app = window.app || {};
app.vm = new Vm();
function Vm(){
var self = this;
self.manual_setpoint = ko.observable("200");
self.manual_setpoint.formatted = function() {
return (parseInt(self.manual_setpoint()) / 10);
};
self.manual_setpoint.formattedAsComputed = ko.pureComputed(function() {
return (self.manual_setpoint() / 10);
});
self.state = ko.observable(true);
self.increment = function(){
var value = parseInt(self.manual_setpoint()) + 1;
self.manual_setpoint(value.toString());
};
self.decrement = function(){
var value = parseInt(self.manual_setpoint()) - 1;
self.manual_setpoint(value.toString());
}
};
ko.applyBindings(app);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="setpoint" data-bind="text: vm.manual_setpoint(), style: { color: vm.state()? '#f00000' : '#777777'}"></div>
<div class="setpoint" data-bind="text: vm.manual_setpoint, style: { color: vm.state()? '#f00000' : '#777777'}"></div>
<div class="setpoint" data-bind="text: vm.manual_setpoint.formatted(), style: { color: vm.state()? '#f00000' : '#777777'}"></div>
<div class="setpoint" data-bind="text: vm.manual_setpoint.formatted, style: { color: vm.state()? '#f00000' : '#777777'}"></div>
<div class="setpoint" data-bind="text: vm.manual_setpoint.formattedAsComputed, style: { color: vm.state()? '#f00000' : '#777777'}"></div>
<div class="setpoint" data-bind="text: vm.manual_setpoint.formattedAsComputed(), style: { color: vm.state()? '#f00000' : '#777777'}"></div>
<button data-bind="click: vm.increment">Increment</button>
<button data-bind="click: vm.decrement">Decrement</button>
<br/>
<pre data-bind="text: ko.toJSON(vm)"></pre>