创建可观察的其他可观察对象作为单个地图

时间:2017-01-18 09:09:17

标签: javascript knockout.js observable

我对numeric中的{em> knockoutJS 输入有自己的绑定,只接受数字。

为了获得大数字,我在NumberField中声明了各种数字实例,如:

var NumberField = function () {
  var self = this;
  self.maskFormat = "0";
  self.firstNumber = ko.observable("");
  self.secondNumber = ko.observable("");
  self.thirdNumber = ko.observable("");
};

并且

<input id="0" maxlength="1" type="tel" data-bind="numeric: firstNumber">
<input id="1" maxlength="1" type="tel" data-bind="numeric: secondNumber">
<input id="2" maxlength="1" type="tel" data-bind="numeric: thirdNumber">

这就像一个魅力,但当我提交时,系统期待一个带有数字的地图。我以丑陋的方式实现了恕我直言:

已添加到NumberField此属性:

this.cleanNumber = ko.pureComputed(function () {
    return this.firstNumber().toString() + this.secondNumber().toString() + this.thirdNumber().toString();
}, this);

在代码中,当我需要使用它时,我必须这样做:

let unwrapNumbers = this.numbers().cleanNumber().split("").map(function (item){
    return Number(item);
});

这很有效,但是......我很确定有一种更容易,更直接的方式......有什么建议吗?

1 个答案:

答案 0 :(得分:2)

我认为将计算结果拆分为两部分会有所帮助:

  1. 获取要按顺序包含的数字
  2. 根据有序值创建字符串
  3. 将计算机分成几个具有单一清晰数据处理职责的纯计算机通常是有意义的。

    &#13;
    &#13;
    var NumberField = function () {
      var self = this;
      self.firstNumber = ko.observable(1);
      self.secondNumber = ko.observable(2);
      self.thirdNumber = ko.observable(3);
      
      self.orderedNumbers = ko.pureComputed(function() {
        return [self.firstNumber,
                self.secondNumber,
                self.thirdNumber].map(ko.unwrap);
      });
      
      self.cleanedNumber = ko.pureComputed(function() {
        return self.orderedNumbers().join("");
      });
    };
    
    var nf = new NumberField();
    
    // If you want the numbers:
    console.log(nf.orderedNumbers());
    
    // If you want the string
    console.log(nf.cleanedNumber());
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    &#13;
    &#13;
    &#13;

    现在,我不确定您的要求是什么,但您可以更进一步,并使用observableArray作为基本数据格式:

    &#13;
    &#13;
    var NumberField = function () {
      var self = this;
      
      self.numbers = ko.observableArray(
        [ko.observable(0), ko.observable(1), ko.observable(2)]);
      
      self.add = function() {
        self.numbers.push(ko.observable(self.numbers().length)); 
      }
      
      self.unwrappedNumbers = ko.pureComputed(function() {
        return self.numbers().map(ko.unwrap);
      });
      
      self.cleanedNumber = ko.pureComputed(function() {
        return self.unwrappedNumbers().join("");
      });
    };
    
    ko.applyBindings(new NumberField());
    &#13;
    label { display: block }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    <div data-bind="foreach: numbers">
      <label>
        <span data-bind="text: 'Number ' + $index()"></span>
        <input type="number" data-bind="textInput: $parent.numbers()[$index()]">
      </label>
    </div>
    <button data-bind="click: add">add</button>
    
    <pre>
    Unwrapped:<code data-bind="text: unwrappedNumbers"></code>
    Cleaned:<code data-bind="text: cleanedNumber"></code>
    </pre>
    &#13;
    &#13;
    &#13;