使用$ .html()时如何提高渲染性能

时间:2017-05-17 20:58:38

标签: javascript jquery backbone.js

我正在开发一个显示推文列表的Backbone demo app。当我替换所有"推文"使用不同的数据我使用 self.label.text = self.stringy

清除列表
$.html()

我想知道是否有人可以给我一些提示,我可以替换这个render: function() { $("#item-table").html(''); this.collection.each(this.addItem); } 以获得更好的性能,因为使用$.html()我会导致回流,并且会给出错误的布局处理时间。

在我使用$.html()的代码中还有另外两个地方,如果有人可以就如果其他地方甚至可能改变这些地方给我提供建议那么真的很棒。

1 个答案:

答案 0 :(得分:3)

Create新的DocumentFragment预渲染所有项目,然后更新DOM一次。

此外,支持this.$(...)优于全局jQuery选择器$(...)

this.$this.$el.find(...)的代理,效率更高,更不容易选择视图之外的内容。

如果视图尚未呈现,则在视图中使用jQuery的核心函数($())可能会失败。因此,最好始终通过this.$el进行操作,以便在视图实际放入DOM之前进行更改。

保持在数组中创建的所有子视图以便以后干净地删除它们。

initialize: function() {
    this.childViews = [];
},
render: function() {
    // cache the list jQuery object
    this.$list = this.$("#item-table");

    // Make sure to destroy every child view explicitely 
    // to avoid memory leaks
    this.cleanup();

    this.renderCollection();
    return this;
},

真正的优化从这里开始,带有一个临时容器。

renderCollection: function() {
    var container = document.createDocumentFragment();

    this.collection.each(function(model) {
        // this appends to a in memory document
        container.appendChild(this.renderItem(model, false).el);
    }, this);

    // Update the DOM only once every child view was rendered.
    this.$list.html(container);
    return this;
},

我们的renderItem函数仍可用于呈现单个项目视图,并立即将其放入DOM中。但它也提供了推迟DOM操作的选项,它只返回视图。

renderItem: function(model, render) {
    var view = new Item({ model: model });

    this.childViews.push(view);
    view.render();
    if (render !== false) this.$list.append(view.el);
    return view;
},

为了避免与悬空侦听器发生内存泄漏,在忘记它之前在每个视图上调用remove非常重要。

我通过将实际调用推迟到remove来使用其他优化,因此我们不会在用户等待时浪费时间。

cleanup: function() {
    var _childViewsDump = [].concat(this.childViews);
    this.childViews = [];

    while (_childViewsDump.length > 0) {
        var currentView = _childViewsDump.shift();
        // defer the removal as it's less important for now than rendering.
        _.defer(currentView.remove.bind(currentView), options);
    }
}