Backbone Model.set不粘?

时间:2012-08-01 18:59:14

标签: backbone.js backbone-events backbone-views

在我的骨干应用程序中,我有一个由模型支持的View,我将模型存储在Collection中。页面上有几个这样的视图,一次只能选择一个。因此,我有另一个包含这些视图集合的视图。当用户单击未聚焦视图时,View会将Model的“focused”属性设置为true。模型上的集合触发一个更改事件,该事件由视图本身处理(将焦点类添加到其$ el) ViewCollection视图,该视图循环遍历集合中的所有视图并取消显示任何聚焦的(除了刚刚点击的那个)。

当我以中等速度点击时,这一切都很有效。但是,当我非常快速地点击时,我发现模型的设置行为存在不一致。也就是说,当我将模型的“聚焦”属性设置为true时,下一个点击事件会显示该模型的“聚焦”属性仍为假。

代码:

    var M = Backbone.Model.extend({
            defaults : {
                            "name" : "",
                "focused" : true
            }
    }),

    L = Backbone.Collection.extend({
            model : M
    }),

    V = Backbone.View.extend({
    events : {
        "click .button" : "focus"
    }
    initialize: function() {
      this.model.bind("change:focused", this.handleFocusChange, this)
    },
    focus: function() {
                console.log("Focus: " + this.model.get("name") + ".focused = " + this.model.get("focused"));

                if (this.model.get("focused")) {
                    return;
                }

                this.model.set({focused: true});  // triggers change event
                this.model.save(this.model);
                console.log("Focus: " + this.model.get("name") + ".focused = " + this.model.get("focused"));
            },
            unfocus: function() {
                console.log("Unfocus: " + this.model.get("name") + ".focused = " + this.model.get("focused"));
                if (!this.model.get("focused")) {
                    return;
                }

                this.model.set({focused: false});  // triggers change event
                this.model.save(this.model);
                console.log("Unfocus: " + this.model.get("name") + ".focused = " + this.model.get("focused"));
            },
            handleFocusChange: function(model, focused) {
                if (focused) {
                    console.log("Handling focus change on " + this.model.get("name") + ", " + this.model.cid);
                    this.$('.button').addClass("focused");
                } else {        
                    console.log("Handling unfocus change on " + this.model.get("nickname") + ", " + this.model.cid);
                    this.$('.button').removeClass("focused");
                }
            }
    }),

    ViewCollection = Backbone.View.extend({
    initialize : function(options) {
                _.bindAll(this, 'initViews');

                this._views = [];

                this.collection.each(this.initViews);
            },
            initViews : function(model) {
                var view = new V({
                    model : model
                });

                this._views.push(view);

                view.model.bind("change:focused", this.focusChanged, this);
            },
            focusChanged: function(changed, focused) {
                if (!focused) {
                    return;
                }

                _.each(this._views, function(view) {
                    if (view.model.id !== changed.id) {
                        view.unfocus();
                    }
                });
            }
    })

以下是上述日志语句的输出:

Click
Focus: A.focused = false
Handling focus change on A, c10
Unfocus: B.focused = false
Unfocus: C.focused = false
Unfocus: D.focused = true
Handling ufocus change on D, c7
Unfocus: D.focused = false
Focus: A.focused = true  <-- good!
Click
Focus: C.focused = false
Handling focus change on C, c9
Unfocus: B.focused = false
Unfocus: A.focused = false  <-- bad!
Unfocus: D.focused = false
Focus: C.focused = true 

正如您所看到的,我首先单击A然后单击C.已更改的事件被触发,View和Collection都表现得恰当。但是,在第二次单击时,A的“聚焦”属性在应该为真时为false。同样,这只发生在我非常迅速地点击视图时。当我以正常速度点击时,我无法重现此问题。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

这需要处理很多,但如果我理解你的设置正确......看起来model.save()的ajax调用失败了。

model.save()是异步的 - 它会在保存调用返回之前触发更改事件。如果保存失败,则撤消更改。尝试以下一项/部分:

  • 看看Firebug,Fiddler或其他什么......
  • 尝试将您的日志记录功能设置为successerror回调,并查看哪些火灾。
  • 添加等待参数(this.model.save(this.model, {wait:true});)并查看日志记录的更改方式。