【发布时间】:2015-02-20 16:46:54
【问题描述】:
在下面的代码中,我将一个项目添加到可观察数组中。这会导致所有先前的项目在执行 .push 时执行其计算的 observable。这是不必要的。如何防止这种情况? 我拥有的项目越多,这意味着计算出的每个项目 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>
js代码
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);
});
【问题讨论】:
-
您的计算函数包含对数组的引用。因此,如果数组发生变化(例如推送),它会触发对所有现有项目的重新计算。
var currentIndex = viewModel.CompanySearchRows.indexOf(self);我不太清楚这个函数是做什么的,所以我不能建议改变 -
嗯,这可能是一个XY problem:您的
computed正在引起副作用并且没有返回任何有意义的结果。计算的 observables 用于读取(有时写入)视图模型上的属性。 -
查看计算函数,我假设该项目正在尝试确定它是否是数组中的最后一项,如果是,插入一个新行?那正确吗。如果是这样,你可能把逻辑放在了错误的地方:让孩子控制父母通常是不好的(我说的是三个孩子的父母!)。我会看看我是否可以创建一个更好的版本,其中主 viewModel 处理添加新行,并且 ItemViewModel 可以忽略它的数组。
-
是的,这就是计算在做什么。如果 companySearchReference 属性发生更改,则检查它是否是最后一行。如果是,则将新行插入父数组。
标签: knockout.js