backbone.js中的双向数据绑定

时间:2012-09-26 15:08:13

标签: backbone.js

我正在开发一个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 source 0.9.2:

_validate: function(attrs, options) {
  if (options.silent || !this.validate) return true;

4 个答案:

答案 0 :(得分:7)

来自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'});

答案 1 :(得分:6)

双向绑定仅表示:

  1. 当模型中的属性更新时,UI也会更新。
  2. 当UI元素更新时,更改会传播回 模型。
  3. Backbone没有&#34;烘焙&#34;实现2选项(虽然你当然可以使用事件监听器)

    在Backbone中,我们可以通过绑定视图&#34;渲染&#34;轻松实现选项1。其模型的方法&#34;变更&#34;事件。要实现选项2,您还需要向input元素添加更改侦听器,并在处理程序中调用model.set。

    检查(jsfiddle.net/sunnysm/Xm5eH/16)js示例,在Backbone中设置双向绑定。

答案 2 :(得分:2)

Backbone.ModelBinder插件非常适合在Backbone Views和Models之间提供双向数据绑定。我写了一篇博文,内容涵盖了这个插件的一些基本功能。这是直接链接:http://niki4810.github.io/blog/2013/03/02/new-post/

答案 3 :(得分:0)

我想看看裸骨代码与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:manual

我使用了这样做的库,例如Epoxy.js(仅缩小了11k)。此外还有其他几个,我建议在使用上面的概念证明代码之前很久。

我会对上面的TwoWayBoundView类可能产生的潜在陷阱和改进感兴趣(但 没有 超出基本的双向绑定请!即我是 寻找要添加的更多功能。)