这里有几种可能性。
1. 中心化:将ClosedTune
对象存储在TuneBook
实例中
存储对每个ClosedTune
in的引用tune_book.tunes
。你如何填充tune_book.tunes
取决于你;既然你提到了一个加法器方法TuneBook
,这就是我在下面说明的。
在事件处理程序中,使用类似事件目标的属性作为键来TuneBook
检索ClosedTune
from 。然后调用or处理程序。tune_book.tunes
id
Tune
ClosedTune
http://jsfiddle.net/p5QMT/1/
var Tune = Backbone.View.extend({
className: "tune",
click_handler: function (event) {
event.preventDefault();
console.log(this.id + " clicked");
},
render: function () {
this.$el.html(
'<a href="" class="button">' + this.id + '</a>'
);
return this;
}
});
var ClosedTune = Tune.extend({});
var OpenTune = Tune.extend({
events: {
"click .button" : 'click_handler'
}
});
var TuneBook = Backbone.View.extend({
events: {
"click .tune .button" : 'click_handler'
},
click_handler: function (event) {
var tune = this.options.tunes[
$(event.target).closest(".tune").attr('id')
];
tune.click_handler( event );
},
add_tune: function (tune) {
this.options.tunes[tune.id] = tune;
this.$el.append(tune.render().el);
},
render: function () {
$("body").append(this.el);
return this;
}
});
var tune_book = new TuneBook({
tunes: {}
});
[1, 2, 3].forEach(function (number) {
tune_book.add_tune(new ClosedTune({
id: "closed-tune-" + number
}));
});
tune_book.render();
var open_tune = new OpenTune({
id: "open-tune-1"
});
$("body").append(open_tune.render().el);
2. 去中心化:将视图对象与 DOM 对象关联起来使用jQuery.data()
当您创建 时ClosedTune
,存储对它的引用,例如this.$el.data('view_object', this)
。
在事件侦听器中,检索ClosedTune
,例如$(event.target).data('view_object')
。
ClosedTune
如果需要,您可以对(in TuneBook
) 和使用相同的处理程序OpenTune
。
http://jsfiddle.net/jQZNF/1/
var Tune = Backbone.View.extend({
className: "tune",
initialize: function (options) {
this.$el.data('view_object', this);
},
click_handler: function (event) {
event.preventDefault();
var tune =
$(event.target).closest(".tune").data('view_object');
console.log(tune.id + " clicked");
},
render: function () {
this.$el.html(
'<a href="" class="button">' + this.id + '</a>'
);
return this;
}
});
var ClosedTune = Tune.extend({
initialize: function (options) {
this.constructor.__super__.initialize.call(this, options);
}
});
var OpenTune = Tune.extend({
events: {
"click .button" : 'click_handler'
}
});
var TuneBook = Backbone.View.extend({
events: {
"click .tune .button": Tune.prototype.click_handler
},
add_tune: function (tune) {
this.$el.append(tune.render().el);
},
render: function () {
$("body").append(this.el);
return this;
}
});
var tune_book = new TuneBook({
tunes: {}
});
[1, 2, 3].forEach(function (number) {
tune_book.add_tune(new ClosedTune({
id: "closed-tune-" + number
}));
});
tune_book.render();
var open_tune = new OpenTune({
id: "open-tune-1"
});
$("body").append(open_tune.render().el);
对评论的回应
我考虑了选项 1,但决定反对它,因为我已经在 Tunebook 中有一组 Tune 模型,并且不想要另一个我需要保持同步的对象
我想这取决于你觉得需要做什么样的家务/同步,以及为什么。
(例如,在 TuneModel.remove() 中,我需要从 Tunebook 的视图列表中删除视图......可能需要事件来执行此操作,因此仅事件解决方案开始看起来更具吸引力)。
为什么你觉得你“需要从 Tunebook 的视图列表中删除视图”?(我并不是建议您不应该这样做,只是问您为什么要这样做。)既然您这样做了,您认为@ggozad 的方法在这方面有何不同?
这两种技术都将ClosedTune
对象存储在TuneBook
实例中。在@ggozad 的技术中,它只是隐藏在一个抽象背后,这可能会让你不那么明显。
在我的示例中,它们存储在一个普通的 JS 对象 ( tune_book.tunes
) 中。在@ggozad 中,它们存储_callbacks
在Backbone.Events
.
添加一个ClosedTune
:
1.
this.options.tunes[tune.id] = tune;
2.
this.on('buttonClick:' + tune.id, tune.handler, tune);
如果你想摆脱 a ClosedTune
(假设你从文档中删除它tune.remove()
并且你希望视图对象完全消失),使用@ggozad 的方法将留下一个孤立的引用ClosedTune
intune_book._callbacks
除非你执行相同类型的内务管理感觉我建议的方法:
1.
delete this.options.tunes[tune.id];
tune.remove();
2.
this.off("buttonClick:" + tune.id);
tune.remove();
每个示例的第一行是可选的——取决于您是否要清理ClosedTune
对象。
选项 2 或多或少是我现在正在做的事情,但是(出于其他原因)我还将模型作为数据属性存储在 view.$el 上,我不禁觉得必须有更好的方法而不是到处存储引用。
好吧,最终归结为您对如何构建事物的偏好。如果您更喜欢以更集中的方式存储视图对象,则可以将它们存储在TuneBook
实例中,而不是使用jQuery.data
. 参见#1:集中式。
您存储对ClosedTune
对象的引用的一种或另一种方式:使用jQuery.data
, 或在 中的普通对象中TuneBook
,或_callbacks
在TuneBook
.
如果您出于理解的原因喜欢@ggozad 的方法,那就去吧,但这不是魔术。正如这里介绍的那样,与我在#1 中提出的更直接的版本相比,我不确定额外的抽象级别应该提供什么优势。如果有一些优势,请随时填写我。