我有一个模型和一个视图。视图显示模型的属性,并允许用户操作这些属性。问题是,当一个属性被修改时,它会重新渲染整个视图,这会给我带来很多问题。
文本输入上的示例模糊事件将新输入保存到属性,从而触发渲染。这意味着如果用户直接点击该文本输入到同一视图上的按钮,则事件将永远不会触发,因为第一个触发的事件将模糊,导致整个视图重新渲染,从而丢失按钮点击事件。 / em>的
我有两个想法:
我似乎更喜欢2.选项。你怎么看?什么是最佳做法?有没有更好的方法来解决这个问题?
答案 0 :(得分:1)
我认为你可以很容易地做到这一点。
退后一步,考虑一下你的活动约束力。您似乎直接将它们绑定在每个单独的元素之上,而不是使用父委托。
这是一个例子
Backbone.View.extend({
el: $("div.parent"),
events: function() {
this.$el.on("click", "input[type=button]", function(){});
// jquery cross browser on this
this.$el.on("blur", "input[type=text]", function(){});
},
initialize: function() {
this.model.bind("change", this.render, this);
},
render: function() {
this.$el.html('<input type="text" /><input type="button" />');
}
});
这是el及其结构的样子
<div class="parent">
<input type="text" />
<input type="button" />
</div>
所以这个。$ el指向div.parent。我可以不断地重新阅读这个内容。$ el,只要html结构没有改变,我就不必担心事件会被解除。另一个解决方案是,如果我真的不能进行委托,那么每当我再次渲染时,我都会调用events方法。
答案 1 :(得分:1)
就像你自己说的那样,你的两个选择看起来都非常复杂。但有时候,复杂性是一种必要的恶魔。但是,如果更新的字段相对简单(比如将值绑定到元素或输入字段),我只需更新DOM元素,而无需在其上创建其他视图/模板抽象。
假设你有一个模特:
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并在View代码中维护它们。但对于更简单的情况,这可能会很有效。
此外,如果它们自然地划分为多个部分,那么尝试构建多个较小视图的视图总是好的。这样您就可以避免单独更新单个字段的需要。