在一次更改多个可观察量时改善淘汰性能

时间:2015-07-20 14:32:04

标签: javascript jquery knockout.js observable batch-updates

对于所提供的JSFiddle中“click”事件的任何性能建议,我将不胜感激。

这个想法是在一次更改多个observable时提高性能。

我无法找到任何关于以批处理方式暂停和恢复更新通知的文档。

http://jsfiddle.net/g9jpxcm2/

$("#all").click(function(){
    var tasks = ko.dataFor($("#tasks")[0]).tasks(),
        checked = this.checked;

    //TODO: performance? Batch changes?
    for(var i = 0, l = tasks.length; i<l; i++){
         tasks[i].done( !!checked );
    }
});

2 个答案:

答案 0 :(得分:2)

通常一个好主意是专注于优雅的解决方案,只有当您遇到性能问题或者至少合理地期望某段代码成为瓶颈时才能优化。

本着这种精神,我编写了一个解决方案,使All复选框的响应速度更快:

  1. 如果选中了所有任务框,则会检查所有任务框
  2. 如果选中全部且未选中任务框,则将取消选中全部
  3. 全部检查会导致检查所有任务框
  4. 取消选中全部会导致取消选中所有任务框
  5. 没有单击事件处理,也没有使用jQuery。虽然每次值发生变化时都会遍历任务项,但我认为您可以拥有一百个任务框并且没有明显的性能问题。

    &#13;
    &#13;
    var viewModel = ko.mapping.fromJS({
    tasks: [{
        name: "Task 1",
        done: false    
    },{
        name: "Task 2",
        done: true    
    },{
        name: "Task 3",
        done: false    
    }]
    });
    
    viewModel.allChecked = ko.computed({
    read: function () {
        var tasks = viewModel.tasks();
        for (var i=0; i<tasks.length; ++i) {
            if (!tasks[i].done()) {
                console.debug("Nope");
                return false;
            }
        }
        return true;
    },
    write: function (newValue) {
        var tasks = viewModel.tasks();
        for (var i=0; i<tasks.length; ++i) {
            tasks[i].done(newValue);
        }
    }
    });
    
    ko.applyBindings(viewModel);
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <script src="https://cdn.rawgit.com/SteveSanderson/knockout.mapping/master/build/output/knockout.mapping-latest.js"></script>
    <label>All</label>
    <input id="all" type="checkbox" data-bind="checked:allChecked" />
    <br><br><br>
    <div id="tasks" data-bind="foreach: tasks">
    <label data-bind="text: name"></label>
    <input type="checkbox" data-bind="checked: done" />    
    </div>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:0)

您可以更改模型以跟踪已检查任务的集合,而不是直接指示检查哪些任务。它应该使实现更容易和更快,因为只有一个observable会更新。只需创建一个(可观察的)数组并将checked绑定绑定到数组。还要确保绑定value

<div id="tasks" data-bind="foreach: tasks">
    <label data-bind="text: name"></label>
    <input type="checkbox" data-bind="checked: $parent.checkedTasks, value: $data" />
</div>
var data = {
    tasks: [{
        name: "Task 1"
    },{
        name: "Task 2"
    },{
        name: "Task 3"
    }]
};

ko.applyBindings( ko.mapping.fromJS(data, {}, {
    checkedTasks: ko.observableArray([])
}), $("#tasks")[0]);

$("#all").click(function(){
    var model = ko.dataFor($("#tasks")[0]),
        checked = this.checked;

    if (checked) {
        model.checkedTasks(model.tasks().slice(0));
    } else {
        model.checkedTasks([]);
    }
});

fiddle