使用 $.html() 时如何提高渲染性能 [英] How to improve rendering performance when using $.html()
问题描述
我正在开发一个显示推文列表的 Backbone 演示应用.当我用不同的数据替换所有推文"时,我使用 $.html()
I am working on a Backbone demo app that shows a list of tweets. As I am replacing all the "tweets" with different data I clear the list using $.html()
render: function() {
$("#item-table").html('');
this.collection.each(this.addItem);
}
我想知道是否有人可以给我一个提示,我可以替换这个 $.html()
以获得更好的性能,因为通过使用 $.html()
我导致回流,这给了糟糕的布局过程时间.
I was wondering if anyone could give me a hint with what can I replace this $.html()
for better performance, because by using $.html()
I am causing reflows and which gives bad layout process times.
我在代码中还有另外两个地方使用了 $.html()
,如果有人能就如何更改这些地方提供建议的话,那就太好了可能.
There are two other places in the code where I use $.html()
and it would be really great if someone could give me advice on how to change those too if those other places are even possible.
推荐答案
创建一个新的DocumentFragment预渲染所有项目,然后更新一次 DOM.
Create a new DocumentFragment to pre-render all the items, then update the DOM once.
另外,支持 this.$(...)
通过全局 jQuery 选择器 $(...)
.
this.$
是 this.$el.find(...)
的代理,它更高效,并且更不容易选择视图之外的内容.
this.$
is a proxy to this.$el.find(...)
which is more efficient, and less prone to select something outside of the view.
如果视图尚未呈现,则在视图中使用 jQuery 的核心函数 ($()
) 可能会失败.因此,最好始终通过 this.$el
进行操作,这样您甚至可以在将视图实际放入 DOM 之前进行更改.
Using jQuery's core function ($()
) inside a view can fail if the view wasn't rendered yet. So it's better to always manipulate through this.$el
so you can make changes even before the view is actually put in the DOM.
将所有创建的子视图保留在一个数组中,以便以后干净地删除它们.
Keep all the sub views created in an array to cleanly remove them later.
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;
},
真正的优化从这里开始,使用一个临时容器.
The real optimization starts here, with a temporary container.
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 操作,它只是返回视图.
Our renderItem
function can still be used to render a single item view and immediatly put it in the DOM. But it also provides an option to postpone the DOM manipulation and it just returns the view.
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
.
To avoid memory leaks with dangling listeners, it's important to call remove
on each view before forgetting about it.
我通过延迟对 remove
的实际调用来使用额外的优化,这样我们就不会在用户等待时浪费时间.
I use an additional optimization by deferring the actual call to remove
so we don't waste time now while the user waits.
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);
}
}
这篇关于使用 $.html() 时如何提高渲染性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!