就像您自己说的那样,您的两种选择似乎都非常复杂。但有时额外的复杂性是一种必要的邪恶。但是,如果更新的字段相对简单(例如将值绑定到元素或输入字段),我会简单地更新 DOM 元素,而无需在它们之上创建额外的 View/Template 抽象。
假设您有一个模型:
var person = new Person({ firstName: 'John', lastName: 'Lennon', instrument:'Guitar' });
以及呈现以下模板的视图:
<div>First Name: <span class="firstName">{{firstName}}</span></div>
<div>Last Name: <span class="lastName">{{lastName}}</span></div>
<div>Instrument: <input class="instrument" value="{{instrument}}"></input></div>
您可以在视图中声明哪个属性更改应该更新哪个元素,并将模型change
事件绑定到更新它们的函数:
var PersonView = Backbone.View.extend({
//convention: propertyName+"Changed"
//specify handler as map of selector->method or a function.
firstNameChanged: { '.firstName': 'text' },
lastNameChanged: { '.lastName': 'text' },
instrumentChanged: { '.instrument': 'val' },
otherFieldChanged: function(val) { //do something else },
initialize: function (opts) {
this.model.on('change', this.update, this);
},
//called when change event is fired
update: function(state) {
_.each(state.changed, function(val, key) {
var handler = this[key + "Changed"];
//handler specified for property?
if(handler) {
//if its a function execute it
if(_.isFunction(handler)) {
handler(val);
//if its an object assume it's a selector->method map
} else if(_.isObject(handler)) {
_.each(handler, function(prop, selector) {
this.$(selector)[prop](val);
}, this);
}
}
}, this);
}
像这样的解决方案不能扩展到非常复杂的视图,因为您必须将分类元素添加到 DOM 并在视图代码中维护它们。但对于更简单的情况,这可能会很好。
此外,如果它们自然地分成多个部分,那么尝试组合多个较小视图的视图总是好的。这样您就可以避免单独更新单个字段的需要。