如何处理自增自减ko.observables浮点数

How to deal with incrementing and decrementing ko.observables floating point

这里准备了一个小jsfiddle:jsfiddle.net/v8s176p2

基本上我想以 0.1 的步长递增和递减 observable 但由于数字表示和精度问题,数字有时会显示 as:1.3200000000000003...等,你我希望它们只显示并具有带 1 个小数点的值

我如何在 knockout.js 中编写完全相同的功能,但不使用浮点数。所以我的起始值为 10,在 HTML 中它显示为 1,如果我将它减去 (10-1 = 9) 在 html 中它显示为 0.9?对于我的应用程序来说,这可能是更好的方法,因为我是从嵌入式设备上的服务器获取这些数据的,所以最好将数字接收为 200,然后将其除以 10,但是如何在 ko.js 在我的示例中 fiddle?

您可以创建一个自定义绑定,像这样

ko.bindingHandlers.numericText = {
    update: function (element, valueAccessor, allBindingsAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        var formattedValue = value.toFixed(2);
        ko.bindingHandlers.text.update(element, function () { return formattedValue; });
    }
};

在那里您可以根据需要格式化值,然后像这样使用它:

<p data-bind="numericText: num1"></p>

处理整数并在文本绑定中进行除法以显示浮点数。这会将支持数据保留为整数,因此不会累积错误。

data-bind="text: num1() / 10"

http://jsfiddle.net/xagup8vt/

另一种方法是将计算的可观察对象添加到可观察对象 属性 中,例如

var vm = function(){
    var self = this;
    self.num1 = ko.observable();
    self.num1.formatted = ko.computed(function(){ return  Math.round((self.num1()*10),0)/10; });
}

这种格式包含在视图模型中,将 vm 对象转换为 JSON 将忽略输出中的格式化计算函数。

要使用它, <p data-bind="text: num1.formatted"></p>

另一种选择是使用可写的计算可观察对象。 我在以下代码段中包含了这两种技术。

var increment = function(observable) {
  observable(observable() + 0.1);
};
var decrement = function(observable) {
  observable(observable() - 0.1);
};

var MyViewModel = function() {
  var self = this;
  self.num1 = ko.observable(0);
  self.num1.formatted = ko.computed(function() {
    return Math.round((self.num1() * 10), 0) / 10;
  });
  var num2BackingProperty = ko.observable(0);
  self.num2 = ko.computed({

    read: function() {
      return num2BackingProperty();
    },
    write: function(value) {
      num2BackingProperty(Math.round((value * 10), 0) / 10);
    },
    owner: self
  })

  this.incrementNum = function(observable) {
    // passing the observable by reference to the helper function
    increment(observable);
  };

  this.decrementNum = function(observable) {
    decrement(observable);
  };
}

ko.applyBindings(new MyViewModel());
h3 {
  font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<button data-bind="click: incrementNum.bind($root, num1)">Increment Num1</button>
<button data-bind="click: decrementNum.bind($root, num1)">Decrement Num1</button>
<h3>
  Formatted
</h3>
<p data-bind="text: num1.formatted"></p>
<h3>
  Unformatted
</h3>
<p data-bind="text: num1"></p>
<br/>
<br/>
<button data-bind="click: incrementNum.bind($root, num2)">Increment Num2</button>
<button data-bind="click: decrementNum.bind($root, num2)">Decrement Num2</button>

<h3>
  Writable Computed
</h3>
<p data-bind="text: num2"></p>
<br/>
<h3>
  View Model Json
</h3>

<pre data-bind="text: ko.toJSON($root)"></pre>

http://jsfiddle.net/gonefishern/yo2nurf8/30/