使用 $.html() 时如何提高渲染性能
How to improve rendering performance when using $.html()
我正在开发一个 Backbone demo app 来显示推文列表。当我用不同的数据替换所有 "tweets" 时,我使用 $.html()
清除列表
render: function() {
$("#item-table").html('');
this.collection.each(this.addItem);
}
我想知道是否有人可以给我一个提示,我可以用什么来替换这个 $.html()
以获得更好的性能,因为使用 $.html()
我会导致回流,这会导致布局处理时间不佳。
我在代码中还有另外两个地方使用了 $.html()
,如果其他地方可能的话,如果有人能给我建议如何更改这些地方,那就太好了。
Create a new DocumentFragment 预渲染所有项目,然后更新 DOM 一次。
此外,this.$(...)
优于全局 jQuery select 或 $(...)
。
this.$
是 this.$el.find(...)
的代理,效率更高,并且不易出现 select 视图之外的东西。
如果尚未呈现视图,则在视图中使用 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 操作的选项,它只是 returns 视图。
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);
}
}
我正在开发一个 Backbone demo app 来显示推文列表。当我用不同的数据替换所有 "tweets" 时,我使用 $.html()
render: function() {
$("#item-table").html('');
this.collection.each(this.addItem);
}
我想知道是否有人可以给我一个提示,我可以用什么来替换这个 $.html()
以获得更好的性能,因为使用 $.html()
我会导致回流,这会导致布局处理时间不佳。
我在代码中还有另外两个地方使用了 $.html()
,如果其他地方可能的话,如果有人能给我建议如何更改这些地方,那就太好了。
Create a new DocumentFragment 预渲染所有项目,然后更新 DOM 一次。
此外,this.$(...)
优于全局 jQuery select 或 $(...)
。
this.$
是 this.$el.find(...)
的代理,效率更高,并且不易出现 select 视图之外的东西。
如果尚未呈现视图,则在视图中使用 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 操作的选项,它只是 returns 视图。
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);
}
}