Create https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment a new 文档片段 https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment预渲染所有项目,然后更新 DOM 一次。
还有,赞成this.$(...) http://backbonejs.org/#View-dollar全局 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;
},
Our 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);
}
}