为了最大程度地减少DOM层次结构的完整呈现,您可以在DOM中设置特殊的节点,以反映给定属性的更新。
让我们使用这个简单的Underscore模板,一个名称列表:
<ul> <% _(children).each(function(model) { %> <li> <span ><%= model.name %></span> : <span ><%= model.name %></span> </li> <% }); %></ul>
注意class
model-<%= model.cid %>-name,这将是我们的注入点。
然后,我们可以定义一个基本视图(或修改Backbone.View),以便在更新这些节点时为其添加适当的值:
var V = Backbone.View.extend({ initialize: function () { // bind all changes to the models in the collection this.collection.on('change', this.autoupdate, this); }, // grab the changes and fill any zone set to receive the values autoupdate: function (model) { var _this = this, changes = model.changedAttributes(), attrs = _.keys(changes); _.each(attrs, function (attr) { _this.$('.model-' + model.cid + '-' + attr).html(model.get(attr)); }); }, // render the complete template // should only happen when there really is a dramatic change to the view render: function () { var data, html; // build the data to render the template // this.collection.toJSON() with the cid added, in fact data = this.collection.map(function (model) { return _.extend(model.toJSON(), {cid: model.cid}); }); html = template({children: data}); this.$el.html(html); return this; }});
代码会有所不同,以适应模型而不是集合。与http://jsfiddle.net/nikoshr/cfcDX/一起玩的小提琴
限制DOM *** 作将渲染委派给子视图可能会花费很多,它们的HTML片段必须插入到父视图的DOM中。看看这个jsperf测试,比较不同的渲染方法
其要点在于,生成完整的HTML结构然后应用视图比构建视图和子视图然后级联呈现要快得多。例如,
<script id="tpl-table" type="text/template"> <table> <thead> <tr> <th>Row</th> <th>Name</th> </tr> </thead> <tbody> <% _(children).each(function(model) { %> <tr id='<%= model.cid %>'> <td><%= model.row %></td> <td><%= model.name %></td> </tr> <% }); %> </tbody> </table></script>var ItemView = Backbone.View.extend({});var ListView = Backbone.View.extend({ render: function () { var data, html, $table, template = this.options.template; data = this.collection.map(function (model) { return _.extend(model.toJSON(), { cid: model.cid }); }); html = this.options.template({ children: data }); $table = $(html); this.collection.each(function (model) { var subview = new ItemView({ el: $table.find("#" + model.cid), model: model }); }); this.$el.empty(); this.$el.append($table); return this; }});var view = new ListView({ template: _.template($('#tpl-table').html()), collection: new Backbone.Collection(data)});
http://jsfiddle.net/nikoshr/UeefE/
请注意,jsperf显示了可以将模板拆分为子模板而不会带来太多损失,这将使您能够为行提供部分渲染。
值得一提的是,不要在连接到DOM的节点上工作,这将导致不必要的重排。在 *** 作它之前,要么创建一个新的DOM,要么分离该节点。
Squash zombies德里克·贝利(DerickBailey)撰写了一篇出色的文章,主题是消除僵尸观点
基本上,您必须记住,丢弃视图时,必须取消绑定所有侦听器并执行任何其他清除 *** 作,例如销毁jQuery插件实例。我使用的是类似于Derick在Backbone.Marionette中使用的方法的组合:
var baseView = Backbone.View.extend({ initialize: function () { // list of subviews this.views = []; }, // handle the subviews // override to destroy jQuery plugin instances unstage: function () { if (!this.views) { return; } var i, l = this.views.length; for (i = 0; i < l; i = i + 1) { this.views[i].destroy(); } this.views = []; }, // override to setup jQuery plugin instances stage: function () { }, // destroy the view destroy: function () { this.unstage(); this.remove(); this.off(); if (this.collection) { this.collection.off(null, null, this); } if (this.model) { this.model.off(null, null, this); } }});
更新我之前的示例以使行具有可拖动的行为,如下所示:
var ItemView = baseView.extend({ stage: function () { this.$el.draggable({ revert: "invalid", helper: "clone" }); }, unstage: function () { this.$el.draggable('destroy'); baseView.prototype.unstage.call(this); }});var ListView = baseView.extend({ render: function () { //same as before this.unstage(); this.collection.each(function (model) { var subview = new ItemView({ el: $table.find("#" + model.cid), model: model }); subview.stage(); this.views.push(subview); }, this); this.stage(); this.$el.empty(); this.$el.append($table); return this; }});
http://jsfiddle.net/nikoshr/yL7g6/
销毁根视图将遍历视图的层次结构并执行必要的清理。
注意:对JS代码感到抱歉,我对Coffeescript不够熟悉,无法提供准确的摘要。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)