javascript - 大量 knockout 嵌套可写计算的性能问题

标签 javascript knockout.js

我有一个 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/

相关文章:

javascript - 如何在某些条件下使用 Angular 8 中的正则表达式添加密码验证?

javascript - npm urllib ResponseTimeoutError - 如何增加超时?

javascript - 使用javascript设置webkit值的正确方法

javascript - knockout 订阅阻塞了页面

javascript - knockout if-else 绑定(bind)无法正常工作

asp.net-mvc - knockout 和 .NET View 模型之间的区别?

javascript - 如何使用基本 KO 可观察数组来更新绑定(bind)到选择选项下拉列表的多个计算可观察数组

Javascript - 函数声明之间的区别

javascript - 客户端证书javascript请求

javascript - 我什么时候应该使用 KnockoutJS 组件和模板?