我的目标是有一个动态增长的输入字段列表-每当我开始输入一个输入字段,一个新的空的应该出现在它下面。
我希望这样的事情能奏效;

function Model() {
    // Build a basic observable array
    this.inputs = ko.observableArray();

    // Whenever this changes, or on initial creation of this computed
    // add a new empty field if the last one has any text in it.
    ko.computed(function () {
        var len = this.inputs().length;
        // If there are no fields (initial run) or the last element is falsey...
        if (!len || this.inputs()[len-1]()) {
            // Create a new observable and add it to the array.
            this.inputs.push(ko.observable(""));
        }
    }, this);
}

下面是一些基本的HTML来绑定模型;
<ul data-bind="foreach: inputs">
    <li><input data-bind="textInput: $data" /></li>
</ul>

当我键入正确显示的文本框(显示此函数确实在创建时运行)时,将不会调用计算结果。
那么,我必须做什么才能让计算结果正确地重新评估呢?有没有更好的方法来实现一个动态增长的列表,实际上在击倒工作?
这里是jsfiddle的确切代码,有助于调试这个问题。

最佳答案

当前实现无法按预期运行有两个原因:
您将输入字段绑定到$data上下文属性,根据docs是提供给可观察对象的字符串。绑定到$rawData属性以绑定到实际的可观察对象。
Computed dependency tracking添加在任何评估运行期间遇到的每个可观测值。推送一个新的可观测数据显然不会增加依赖性。将可观测数组初始化为单个可观测数组将是一个解决方案。这样,也可以删除!len检查。

function Model() {
  this.inputs = ko.observableArray([ko.observable("")]);

  ko.computed(function() {
    if (!!this.inputs()[this.inputs().length - 1]()) {
      this.inputs.push(ko.observable(""));
    }
  }, this);
}

ko.applyBindings(new Model());

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: inputs">
  <li>
    <input data-bind="textInput: $rawData" />
  </li>
</ul>

下面是另一个程序。它递归地加上一个可观测值。添加可观察对象时,将创建订阅以跟踪其更改。当它更改为非空值时,将释放订阅(仅需要一次),并重复该例程。
function Model() {
  this.inputs = ko.observableArray();

  this.addItem = function() {
    var newItem = ko.observable("");
    this.inputs.push(newItem);
    var sub = newItem.subscribe(function(newValue) {
      if (!!newValue) {
        sub.dispose();
        this.addItem();
      }
    }, this);
  }

  this.addItem();
}
ko.applyBindings(new Model());

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: inputs">
  <li>
    <input data-bind="textInput: $rawData" />
  </li>
</ul>

09-25 16:18