我正在使用backbone.js构建一个应用程序,并在模型视图的模板中找到了一个包含大量条件逻辑的视图。模型的type
属性用于确定要呈现的html。如果可能的话,我想避免这种逻辑,因为它很难阅读。我认为有两种方法可以解决这个问题(请注意,我在这里获得的实际模板非常简单):
1。集合视图中的条件逻辑而非模型视图 - 多个子视图
我可以将作用于每个模型的条件逻辑放入集合视图中:
var CollectionView = Backbone.View.extend({
....
render: function() {
this.collection.each(function(thing) {
if(thing.get("type") === "wotsit") {
this.$el.append(new WotsitView({ model: thing });
} else if(thing.get("type") === "oojamaflip") {
this.$el.append(new OojamaflipView({ model: thing });
}
}, this);
},
....
}
赞成 这样我可以让每个子视图都有一个没有逻辑的模板方法,而只是构建html。
var WotsitView = new Backbone.View.extend({
....
template: _.template('<h2>{{ title }}</h2>');
});
var OojamaflipView = new Backbone.View.extend({
....
template: _.template('<h3>{{ title }}</h3>');
});
缺点
问题是,集合中的thing
都非常相似。每个thing
的事件可能相同或非常相似,我可以看到存在大量代码重复。我真的只希望这些子视图的实际模板与其他一切相同。
2。模型视图中的条件逻辑 - 多模板方法
var ModelView = Backbone.View.extend({
....
render: function() {
if(this.model.get("type") ==== "wotsit") {
this.$el.html(this.wotsitTemplate(this.model.attributes));
} else if(this.model.get("type") === "oojamaflip") {
this.$el.html(this.oojamaflipTemplate(this.model.attributes));
}
},
wotsitTemplate: _.template('<h2>{{ title }}</h2>'),
oojamaflipTemplate: _.template('<h3>{{ title }}</h3>')
});
赞成 该模型只有一个视图。 所有事件等都是一个视图中的句柄而不是重复。
缺点 我其实非常喜欢这种方式,但我很想听听其他人的选择。
答案 0 :(得分:4)
选项#1 =多态
选项#2 =开关语句
如果您从未(或很少)必须添加新类型,则切换语句很有用,但您可能希望添加新方法。想象一下,您希望向validate
添加ModelView
方法,该方法检查该类型模型的视图输入是否正确,并将结果报告给用户。使用选项#2,您只需添加一个新方法来切换模型类型(就像render
方法一样)来处理验证。
现在让我们假设我们已经有render
方法和validate
方法,我们想要处理一种新型号thingamajig
。使用选项#2,您必须为render
和validate
添加逻辑。现在想象一下,我们不会只有2种方法,但是当你必须处理新类型时,10 - 选项#2会变得非常复杂。但是如果我们遵循选项#1,那么无论有多少种方法,我们只需要在一个地方创建一个新视图,并更新CollectionView
以将新类型映射到新视图。
大多数情况下,多态(选项#1)是干净的方法。它允许您将特定于给定类型的所有逻辑分开并将其放在一个位置,从而可以轻松处理新类型。
如果您对选项#1感到担心,您在所有观看次数之间会遇到大量重复代码,请不要忘记将视图设为很容易继承自其他骨干视图:
var ItemView = Backbone.View.extend({
initialize: function() {
/* some common logic for all views */
}
});
var WotsitView = ItemView.extend({
template: _.template('<h2>{{ title }}</h2>')
});
var OojamaflipView = ItemView.extend({
template: _.template('<h3>{{ title }}</h3>')
});