我有一个淘汰赛应用程序,我有一个可写的可编程Observables层次结构,如下所示:
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
});
}
问题是当选择了parentVM时(通过复选框),渲染所有复选框并更新总金额需要30-40秒。大约有4500个发票和大约274家公司(但只有公司正在展示,发票被隐藏使用display:none)。我已经尝试使用延迟更新插件限制可观察量,使用和不使用deferEvaluation选项,通过jQuery手动选择复选框(它没有使用2路绑定)。有没有人有关于加快这个过程的建议?在此先感谢您的帮助!
答案 0 :(得分:1)
我注意到了一些事情:
isSelected
的写入中,因为您正在更新read
函数的依赖关系的值,所以在更新每个isSelected
时会反复触发计算。您可以使用限制器(或3.1中的rateLimit
)扩展器来确保读取功能不会被调用。
在read
函数中,一旦找到错误值,就可以立即退出。在这种情况下,您不需要遍历所有值。
每个totalSelectedAmount
更新后,isSelected
也会重新计算。对于throttle
/ rateLimit
来说,这也是一个不错的选择。
尽管如此,同步更新仍然需要大量数据。可能值得为isSelected
中的每个公司(或一大块公司)更新setTimeout
,以确保在整个处理期间不冻结浏览器。
以下是包含许多此类更改的示例:http://jsfiddle.net/rniemeyer/k4vJ8/。我可能会考虑在每个setTimeout上更新一大块公司,而不是一次更新一个公司。
答案 1 :(得分:0)
加快速度的一种方法是在ko.observableArray
的基础数组上运行操作。例如,您可以更改此
for (var i = 0; i < self.invoices().length; i++)
self.invoices()[i].isSelected(value);
到这个
var underlying = self.invoices();
for (var i = 0; i < underlying.length; i++)
underlying[i].isSelected(value);
self.invoices.valueHasMutated();
如果您的ko.observableArray
包含许多元素(与您的元素相同),那么这样做肯定会为您带来显着的速度提升。您发布的代码中有多个位置可以实现此目的。有关详细信息,请参阅Knockout.js Performance Gotcha #2 - Manipulating observableArrays。
答案 2 :(得分:0)
尝试在self.companies()
self.companies()
,for
..等
observableArray()
它是一个函数,当你调用observableArray()
得到一个真实的对象时,你可以调用它一次。
看看