我有一个包含CellMolls CellCollection的BoardView。我从数据库中获取集合,然后创建CellViews。
这一切都在游泳,直到我尝试通过BoardView上的点击事件访问CellModel。我根本无法获得基础模型......只有视图。有没有办法做到这一点?
我试图在下面加入相关代码:
CellModel = Backbone.Model.extend({});
CellCollection = Backbone.Collection.extend({
model : CellModel
});
CellView = Backbone.View.extend({
className : 'cell',
});
BoardView = Backbone.View.extend({
this.model.cells = new CellCollection();
render : function() {
this.cellList = this.$('.cells');
return this;
},
allCells : function(cells) {
this.cellList.html('');
this.model.cells.each(this.addCell);
return this;
},
addCell : function(cell) {
var view = new Views.CellView({
model : cell
}).render();
this.cellList.append(view.el);
},
events : {
'click .cell' : 'analyzeCellClick',
},
analyzeCellClick : function(e) {
// ?????????
}
});
我需要在BoardView上点击“发生”,而不是CellView,因为它涉及特定于电路板的逻辑。
答案 0 :(得分:12)
好问题!我认为最好的解决方案是实现
EventBus 又名 EventDispatcher
协调应用程序不同区域之间的所有事件。
走这条路线似乎干净,松散耦合,易于实施,可扩展,实际上是由骨干文档建议的,请参阅Backbone Docs
请同时阅读有关here和here主题的更多信息,因为(即使我努力了),我自己的解释对我来说似乎有些平庸。
五步说明:
在您的主要或其他地方创建一个EventBus作为util并包含/要求
var dispatcher = _.clone(Backbone.Events); // or _.extends
向其添加一个或多个回调hanlder
dispatcher.CELL_CLICK = 'cellClicked'
将一个触发器添加到childView的Eventlistener(此处:CellView)
dispatcher.trigger(dispatcher.CELL_CLICK , this.model);
将监听器添加到parentView的Initialize函数(此处:BoardView)
eventBus.on(eventBus.CARD_CLICK, this.cardClick);
在parentView中定义相应的回调(并将其添加到_.bindAll)
cellClicked: function(model) { // do what you want with your data here console.log(model.get('someFnOrAttribute') }
答案 1 :(得分:11)
我可以想到你可能会在这里使用至少两种方法:
在初始化时将BoardView传递给CellView,然后在CellView中处理事件:
var CellView = Backbone.View.extend({
className : 'cell',
initialize: function(opts) {
this.parent = opts.parent
},
events : {
'click' : 'analyzeCellClick',
},
analyzeCellClick : function() {
// pass the relevant CellModel to the BoardView
this.parent.analyzeCellClick(this.model);
}
});
var BoardView = Backbone.View.extend({
// ...
addCell : function(cell) {
var view = new Views.CellView({
model : cell,
parent : this
}).render();
this.cellList.append(view.el);
},
analyzeCellClick : function(cell) {
// do something with cell
}
});
这样可行,但我更倾向于没有视图调用彼此的方法,因为它使它们更紧密耦合。
渲染时将CellModel id附加到DOM:
var CellView = Backbone.View.extend({
className : 'cell',
render: function() {
$(this.el).data('cellId', this.model.id)
// I assume you're doing other render stuff here as well
}
});
var BoardView = Backbone.View.extend({
// ...
analyzeCellClick : function(evt) {
var cellId = $(evt.target).data('cellId'),
cell = this.model.cells.get(cellId);
// do something with cell
}
});
这可能有点清洁,因为它避免了上面提到的紧耦合,但我认为无论哪种方式都可行。
答案 2 :(得分:6)
我会让CellView
处理click事件,但它只会触发Backbone事件:
var CellView = Backbone.View.extend({
className : 'cell',
initialize: function() {
_.bindAll(this, 'analyzeCellClick');
}
events : {
'click' : 'analyzeCellClick',
},
analyzeCellClick : function() {
this.trigger('cellClicked', this.model);
}
});
var BoardView = Backbone.View.extend({
// ...
addCell : function(cell) {
var view = new Views.CellView({
model : cell
}).render();
this.cellList.append(view.el);
view.bind('cellClicked', function(cell) {
this.analyzeCellClick(cell);
};
},
analyzeCellClick : function(cell) {
// do something with cell
}
});