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