如何将从 json 接收到的 ko.observable 字符串解析为整数(数字)值
Posted
技术标签:
【中文标题】如何将从 json 接收到的 ko.observable 字符串解析为整数(数字)值【英文标题】:how to parse ko.observable string received from json to integer (number) value 【发布时间】:2020-07-05 03:08:01 【问题描述】:我在 ViewModel 中从服务器的 json 响应中获取了一个字符串。 它看起来像这样:
"manual_setpoint": "200",
然后我需要在我的视图中显示它:
<div class="setpoint" data-bind="text: vm.manual_setpoint(), style: color: vm.state()? '#f00000' : '#777777'"></div>
它需要显示为数字 20 (200/10),因为有用于增加和减少可观察的按钮(例如 201->20.1、199->19.9)。当我的 observable 被本地定义为数字时,这不是问题。我是这样做的:
self.manual_setpoint.formatted = function()
return (self.manual_setpoint() / 10);
;
然后在我的视图中显示 manual_setpoint.formatted()。我也有用于增加和减少这个 observable 的按钮,如下所示:
self.decSetpoint = function (observable)
decrement(observable);
;
var decrement = function (observable)
observable(observable() - 1);
;
现在当服务器的响应是字符串时,我的方法不再起作用。 (例如,对于 200 + 1,我得到 2001 等....)
如何以最简单优雅的方式处理这种情况? 我需要在我的视图中显示正确的数字(所以对于 200 我需要 20)并且我必须能够 像以前一样递增和递减相同的可观察对象
【问题讨论】:
您能否更新 JSON,使其以数字而不是字符串的形式发送,因为这似乎是根本问题? 不幸的是,我无法更改 JSON。此外,这是一个有趣的情况,我认为很容易解决。但是从这个意义上说ko.js有点复杂,所以我想学习如何解决它 它是如何从服务器 JSON 数据转换为 observable 的? 在 ko.js 应用程序内部使用 ko.map.fromjs 处理,但与问题无关。 【参考方案1】:继@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_setpoint 更改时,格式化版本也会更新。
编辑
好吧,我认为需要将 pureComputed 用于格式化函数。使用这个基本测试,似乎只使用一个函数就可以按预期工作。长期以来,我的理解是,添加一个以某种方式包装 observable 的函数将执行一次,并且如果在包装函数执行后(通常在绑定过程中)更新了包装的 observable,则不会更新。所以当视图绑定到包装函数时,视图不会被更新,因为返回的函数是不可观察的。
此外,根据测试,似乎 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>
【讨论】:
感谢您的回答。你能解释一下为什么纯计算会有所不同吗?此外,self.manual_setpoint 的值(将其传递回服务器时)是字符串还是数字?以上是关于如何将从 json 接收到的 ko.observable 字符串解析为整数(数字)值的主要内容,如果未能解决你的问题,请参考以下文章
如何将从数据库接收到的数据作为道具传递给 Reactjs 中的另一个组件