javascript - 包含可观察对象的动态增长的 observableArray

标签 javascript html knockout.js

我的目标是拥有一个动态增长的输入字段列表 - 每当我开始在一个输入字段中输入内容时,它下面应该会出现一个新的空白字段。

我希望这样的事情能奏效;

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);
}

下面是绑定(bind)模型的一些基本 HTML;

<ul data-bind="foreach: inputs">
    <li><input data-bind="textInput: $data" /></li>
</ul>

当我在正确显示的文本框中输入内容时(显示此函数确实在创建时运行),计算不会被调用。

那么我必须怎么做才能让计算器正确地重新评估?有没有更好的方法来实现在 knockout 中实际有效的动态增长列表?

这里是 jsfiddle我这里有确切的代码,以帮助调试这个问题。

最佳答案

当前实现没有按预期运行的原因有两个:

  1. 您将输入字段绑定(bind)到 $data 上下文属性,根据 docs是提供给可观察对象的字符串。绑定(bind)到 $rawData 属性以绑定(bind)到实际的可观察对象。
  2. Computed dependency tracking添加它在任何评估运行期间遇到的每个可观察对象。推送一个新的可观察对象显然不会增加依赖性。将 observable 数组初始化为单个 observable 将是解决此问题的方法。通过这样做,也可以删除 !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>

关于javascript - 包含可观察对象的动态增长的 observableArray,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39949869/

相关文章:

javascript - 带有 <select> 元素的 jQuery focus() 事件的无限循环

knockout.js - KnockoutJS - 显示文本框中逗号分隔的 observableArray 的内容

javascript - JavaScript 可以访问自动填充密码吗?

html - 如何在 CSS 中指定复杂的绝对引用

jquery - 嵌套两列高度问题

css - 如何将滚动添加到 django 渲染表?

javascript - knockout js 错误 String 不是函数

JavaScript 和 knockoutjs 此关键字的奇怪行为

javascript - 休息 API : how to pass the JSONresponse to Javascript?

javascript - 直接分配的事件处理程序是实际的对象属性吗?