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

IT技术 javascript jquery backbone.js
2021-03-19 09:58:07

我正在开发一个显示推文列表的Backbone演示应用程序当我用不同的数据替换所有“推文”时,我使用$.html()

render: function() {
    $("#item-table").html('');
    this.collection.each(this.addItem);
}

我想知道是否有人可以给我一个提示,我可以用什么替换它$.html()以获得更好的性能,因为通过使用$.html()我会导致回流并导致错误的布局过程时间。

我使用的代码中还有另外两个地方,$.html()如果有人能就如何更改这些地方提供建议,那真是太好了。

1个回答

创建一个新的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);
    }
}
@gfels 如果,通过KVO 视图模型同步机制,您的意思是双向数据绑定,那么 Backbone 也没有提供,并且有专门用于此的库可以轻松地与 Backbone 一起使用。(Epoxy, Knockout, Backbone.Stickit, 甚至可以使用 React)
2021-04-22 09:58:07
谢谢!与 React(虚拟 DOM)相比,我将为这个应用程序做一个基准测试,我使用这个 Backbone 应用程序作为 KVO(键值观察)视图模型同步机制的一个例子。我只是想确定 - 如果我实施这些优化,这个应用程序是否仍然是 KVO 视图模型同步机制的一个很好的例子?
2021-04-30 09:58:07
@gfels 对不起,我不熟悉 KVO 视图模型同步机制。至于对比Backbone渲染和React,这无关紧要,因为Backbone不提供渲染,一切都留给开发者使用他喜欢的东西。Backbone 默认仅提供 jQuery,但仍允许开发人员实现应用程序渲染。
2021-05-09 09:58:07
@gfels 只是为了添加我的两分钱,如果您尝试使用主干实现 2way 绑定,请参阅Rivets.jsSkateJS
2021-05-11 09:58:07