我有一个我想在表视图中呈现的模型集合.每个模型应该由表中的单个行表示,并且应使用模板生成此行.我应该能够将事件处理程序附加到该行(例如单击),在事件警报时,将显示与该行关联的模型的某些特定信息.
我已经看到类似的事情的一个常见的方法是将每一行分解成自己的视图,并且有一个父视图(让我们说这种情况下的表)使用行视图来生成包含在你的代码中的html .但是,我无法弄清楚如何使用模板.
在这种情况下,我不能将事件专门附加到RowView,因为它没有引用dom元素(this.el为骨干),它只是返回一个字符串.如何实现我想要的,同时使用模板最大的容量?
问题不在于事件,模板或使用嵌套视图,更多的是使用Backbone来实现这种输出的正确方法.
/** View representing a table */ var TableView = Backbone.View.extend({ tagName: 'table',render: function() { var rows = _.map(this.collection.models,function(p) { return new RowView({model: p}).render(); }); $('body').html(this.$el.html(rows.join(''))); } }); /** View representing a row of that table */ var RowView = Backbone.View.extend({ render: function() { // imagine this is going through a template,but for now // lets just return straight html. return '<tr>' + '<td>' + this.model.get('name') + '</td>' + '<td>' + this.model.get('age') + '</td>' + '</tr>'; } }); var data = [ {'name': 'Oli','age': 25},{'name': 'Sarah','age': 20}]; /** Collection of models to draw */ var peopleCollection = new Backbone.Collection(data); var tableView = new TableView({collection: peopleCollection}); tableView.render();
谢谢!
解决方法
处理视图层次结构的一种方法是让每个视图呈现其子节点并将其附加到其el.然后根据其模型/集合,每个视图处理事件.
要将HTML注入视图el,因此控制容器元素,可以使用setElement方法
setElement
view.setElement(element)
If you’d like to apply a Backbone
view to a different DOM element,use setElement,which will also
create the cached $el reference and move the view’s delegated events
from the old element to the new one.
你的例子可以重写为
var rowTemplate=_.template("<tr>"+ "<td class='name'><%= name %></td>"+ "<td class='age'><%= age %></td>"+ "</tr>"); /** View representing a table */ var TableView = Backbone.View.extend({ tagName: 'table',initialize : function() { _.bindAll(this,'render','renderOne'); },render: function() { this.collection.each(this.renderOne); return this; },renderOne : function(model) { var row=new RowView({model:model}); this.$el.append(row.render().$el); return this; } }); /** View representing a row of that table */ var RowView = Backbone.View.extend({ events: { "click .age": function() {console.log(this.model.get("name"));} },render: function() { var html=rowTemplate(this.model.toJSON()); this.setElement( $(html) ); return this; } }); var data = [ {'name': 'Oli','age': 20}]; /** Collection of models to draw */ var peopleCollection = new Backbone.Collection(data); var tableView = new TableView({collection: peopleCollection}); $("body").append( tableView.render().$el );