我有一个 knockout 应用程序,其中有可写计算可观察量的层次结构,如下所示:
function InvoiceVM() {
self.isSelected = ko.observable()
self.selectedAmount = ko.computed(function() {
if (self.isSelected())
return self.usdBalance;
else
return 0;
}
}
function CompanyVM() {
self.invoices = ko.observableArray()
self.totalSelectedAmount = ko.computed(function () {
var total = 0;
for (var i = 0; i < self.invoices().length; i++) {
total += self.invoices()[i].selectedAmount();
}
return total;
});
self.isSelected = ko.computed({
read: function () {
var isSelected = true;
for (var i = 0; i < self.invoices().length; i++) {
if (!self.invoices()[i].isSelected())
isSelected = false;
}
return isSelected;
},
write: function (value) {
for (var i = 0; i < self.invoices().length; i++)
self.invoices()[i].isSelected(value);
},
deferEvaluation: true,
owner: self
})
}
function ParentVM() {
self.companies = ko.observableArray()
self.isSelected = ko.computed({
read: function () {
var isSelected = true;
for (var i = 0; i < self.funds().length; i++) {
if (!self.companies()[i].isSelected()) {
isSelected = false;
break;
}
}
return isSelected;
},
write: function (value) {
for (var i = 0; i < self.companies().length; i++) {
var currentCompany = self.companies()[i];
for (var j = 0; j < currentCompany.invoices().length; j++)
currentCompany.invoices()[j].isSelected(value);
}
},
deferEvaluation: true
});
}
问题是,当选择父虚拟机(通过复选框)时,需要 30-40 秒来呈现所有复选框并更新总量。大约有 4500 张发票和大约 274 个公司(但只显示公司,发票使用 display:none 隐藏)。我尝试过使用延迟更新插件(带或不带 deferEvaluation 选项)来限制可观察值的速率,通过 jQuery 手动选择复选框(这不适用于 2 路绑定(bind))。有人对加快这一过程有建议吗?预先感谢您的帮助!
最佳答案
我注意到一些事情:
在写入
isSelected
时,由于您正在更新依赖于read
函数的值,因此您在更新每个值时会一遍又一遍地触发计算已选择
。您可以使用throttle(或3.1中的rateLimit
)扩展器来确保读取函数不会继续被调用。在您的
read
函数中,一旦发现错误值,您就可以真正退出。在这种情况下,您不需要循环遍历所有值。当每个
isSelected
更新时,totalSelectedAmount
也会重新计算。这对于throttle
/rateLimit
来说也是一个很好的选择。
尽管如此,仍有大量数据需要同步更新。可能值得在 setTimeout
中为每个公司(或一部分公司)更新 isSelected
,以确保浏览器在整个处理过程中不会被卡住。
以下是包含许多这些更改的示例:http://jsfiddle.net/rniemeyer/k4vJ8/ 。我可能会考虑在每个 setTimeout 上更新一大堆公司,而不是一次更新一个公司。
关于javascript - 大量 knockout 嵌套可写计算的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23703774/