在下面的代码中,我将一个项添加到observable数组中。这会导致所有先前的项在执行.push时执行其计算的observable。这是不必要的。怎么预防这个? 我拥有的项目越多,就意味着将运行每个计算出的可观察项目。
请参阅小提琴示例。 http://jsfiddle.net/k8kbdnnv/3/
html代码
<div id="logs"></div>
<table>
<tbody data-bind="foreach: CompanySearchRows">
<tr >
<td>
<input data-bind='textInput: ClientReference' type="text" />
</td>
<td>
<input data-bind='textInput: CompanySearchReference' type="text" />
</td>
</tr>
</tbody>
</table>
jscode
var viewModel;
var maxTitleRefRows = 50;
function ViewModel() {
var self = this;
self.CompanySearchRows = new ko.observableArray([new ItemViewModel()]);
self.Executions = ko.observable(0);
self.addRow = function (clientReference) {
var newRow = new ItemViewModel();
self.CompanySearchRows.push(newRow); //this causes the code to jump
into each array item's OnCompanySearchReferenceChanged computed observable
};
}
function ItemViewModel() {
var self = this;
self.ClientReference = ko.observable("");
self.CompanySearchReference = ko.observable("");
self.OnCompanySearchReferenceChanged = ko.computed(function () {
var reference = self.CompanySearchReference();
logIt("computed executed" + reference);
if (reference !== "" ) {
var currentIndex = viewModel.CompanySearchRows.indexOf(self);
viewModel.Executions(currentIndex);
var length = viewModel.CompanySearchRows().length;
var lastItemIndex = length - 1;
if (currentIndex === lastItemIndex && length < maxTitleRefRows ) {
viewModel.addRow(self.ClientReference());
}
}
return;
});
}
var logs=document.getElementById('logs');
function logIt(msg){
var e=document.createElement('div');
e.innerHTML=msg;
logs.insertBefore(e,logs.firstChild);
}
$(document).ready(function () {
viewModel = new ViewModel();
ko.applyBindings(viewModel);
});
答案 0 :(得分:0)
computed
函数包含对主ViewModel中observableArray
的引用。这意味着如果数组发生更改(例如,从push
)所有,则会重新评估所有项目上的计算函数。
读取代码时,计算函数的意图似乎是在第二个字段中输入值时添加新行。因此,我们只需跟踪 last 项即可执行此操作。通常建议不要在子对象内部执行此操作 - 主viewModel应该管理数组,子应该独立于它。
为实现这一目标,我在CompanySearchReference
可观察对象上使用subscription ,但仅在最后一项上使用http://jsfiddle.net/Quango/fgfw6Ld0/。当此值更改时,父ViewModel将添加新行,并且还会删除上一行的订阅,因此任何时候只有一个订阅处于活动状态。
// subscribe to changes on the child's search reference
// when this has a value, create a new row
var subscription = newRow.CompanySearchReference.subscribe(function (newValue) {
if (newValue && self.CompanySearchRows().length < maxTitleRefRows) {
// value has been changed: first remove this subscription
logIt("removing subscription");
subscription.dispose();
// add a new row (creates a new subscription on new row)
logIt("adding new row");
self.addRow();
}
});
完整的JSFiddle位于{{3}}