我正在开发一个jQuery Backbone.js Web应用程序。
就像在Adobe Flex中一样,我在我的应用程序中实现了双向数据绑定
输入元素/小部件。
因此,每个输入元素/小部件都知道其对应的模型和模型属性名称。
当用户点击标签或输入时,字段值将自动提供给模型。
container.model.set(this.attrName, this.value, options); // command 1
在另一个方向,当模型从后端更新时,视图
输入元素/小部件应该自动获取
更新:
container.model.bind("change:"+ this.attrName, this.updateView, this); // command 2
问题是:
当用户点击进入并且模型自动更新时,“更改:abc”也是
触发和this.updateView被调用,不仅在新模型来自时
后端。
到目前为止我的解决方案是在用户按下enter(命令1)时设置模型值时传递选项“source:gui”,并在我的updateView方法中检查它。但我不再满足于这个解决方案了。
有人有更好的解决方案吗?
非常感谢提前
沃尔夫冈
更新:
当传递选项silent:true时,不会调用模型的validate方法,因此
这没有用。请参见Backbone.js源代码0.9.2:
_validate: function(attrs, options) {
if (options.silent || !this.validate) return true;
来自Backbone.js网站:
除非{silent:true}作为选项传递,否则将触发“更改”事件
options.silent = true;
container.model.set(this.attrName, this.value, options);
更新:
您在问题中添加了新评论,因此我只是补充了我的答案,以修复您提到的新用例(验证流程):
var ExtendedModel = Backbone.Model.extend({
uiChange : false,
uiSet: function (attributes, options, optional) {
this.uiChange = true;
this.set(attributes, options, optional);
this.uiChange = false;
}
});
var MyModel = ExtendedModel.extend({
});
var model = new MyModel();
model.on('change:name', function(){
console.log('this.uiChange: ', this.uiChange);
});
//simulates the server side set
model.set({name:'hello'});
//simulates the ui side set you must use it to set from UI
model.uiSet({name:'hello2'});
来自Backbone.js网站:
除非{silent:true}作为选项传递,否则将触发“更改”事件
options.silent = true;
container.model.set(this.attrName, this.value, options);
更新:
您在问题中添加了新评论,因此我只是补充了我的答案,以修复您提到的新用例(验证流程):
var ExtendedModel = Backbone.Model.extend({
uiChange : false,
uiSet: function (attributes, options, optional) {
this.uiChange = true;
this.set(attributes, options, optional);
this.uiChange = false;
}
});
var MyModel = ExtendedModel.extend({
});
var model = new MyModel();
model.on('change:name', function(){
console.log('this.uiChange: ', this.uiChange);
});
//simulates the server side set
model.set({name:'hello'});
//simulates the ui side set you must use it to set from UI
model.uiSet({name:'hello2'});
双向绑定意味着:
- 当模型中的属性更新时,UI也会更新。
- 当UI元素更新时,更改会传播回
模型。
Backbone没有2个选项的“烘焙”实现(尽管你当然可以使用事件监听器来实现)
在Backbone中,我们可以通过将视图的“render”方法绑定到其模型的“change”事件来轻松实现选项1。要实现选项2,您还需要向input元素添加更改侦听器,并在处理程序中调用model.set。
检查(jsfiddle.net/sunnysm/Xm5eH/16)jsfiddle示例,在Backbone中设置双向绑定。
Backbone.ModelBinder
插件非常适合在Backbone Views和Models之间提供双向数据绑定。我写了一篇博文,介绍了这个插件的一些基本功能。这是直接链接: http://niki4810.github.io/blog/2013/03/02/new-post/
我想看看裸骨代码与Backbone.js的双向绑定是什么。这就是我提出的:
var TwoWayBoundView = Backbone.View.extend({
initialize: function(options) {
this.options = _.defaults(options || {}, this.options);
_.bindAll(this, "render");
this.model.on("change", this.render, this);
this.render();
},
events: {
"change input,textarea,select": "update"
},
// input updated
update: function(e) {
this.model.set(e.currentTarget.id, $(e.currentTarget).val());
},
// model updated...re-render
render: function(e) {
if (e){
var id = Object.keys(e.changed)[0];
$('#'+id).val(e.changed[id]);
}
else{
_.each(this.model.attributes, function(value, key){
$('#'+key).val(value);
});
}
}
});
用法:
var model = new Backbone.Model({ prop1: "uno 1", prop2: "dos 2", prop3: "3" });
var view = new TwoWayBoundView({
el: "#myContainer",
model: model
});
这是一个jsbin: http://jsbin.com/guvusal/edit?html,js,console,output
我已经使用了这样做的库,例如Epoxy.js(仅缩小了11k)。此外还有其他几个,我建议在使用上面的概念验证代码之前很久。
我会对上面的TwoWayBoundView类可能产生的潜在陷阱和改进感兴趣(但是 没有超越基本的双向约束请!即我 不 寻找更多要添加的功能。)