2012-08-01 56 views
0

在我的骨干应用程序中,我有一个由模型支持的View,并将模型存储在Collection中。页面上有几个这样的视图,一次只能选择一个视图。因此,我有另一个视图包含这些视图的集合。当用户点击未聚焦的视图时,视图将模型的“聚焦”属性设置为true。模型集触发视图本身处理的变化事件(将焦点类添加到它的$ el) ViewCollection视图,该视图循环访问集合中的所有视图,并忽略它们中的任何视图专注(除了刚刚点击的那个)。Backbone Model.set不粘?

这一切都很好,当我点击一个中等速度。但是,当我点击的速度很快时,我发现模型的行为不一致。也就是说,当我将模型的“焦点”属性设置为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的“聚焦”属性在应该为真时为假。再次,这只发生在我非常快速地点击视图时。当我以正常速度点击时,我无法重现此问题。

任何帮助将不胜感激!

回答

1

这是一个很多过程,但如果我理解您的设置正确....它看起来像从model.save() ajax调用失败。

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

  • 看萤火虫,提琴手,或任何会发生什么...
  • 尝试把你的日志功能为successerror回调,看看哪火灾。
  • 添加等待参数(this.model.save(this.model, {wait:true});)并查看日志记录如何变化。
+0

好吧,我想你可能会在这里。我完全删除了保存电话,但无法重现此问题。但是,当我将其添加回来时,我添加了错误/成功处理程序,并且在问题确实返回时,所有保存回调都成功了。等待参数在这里不合适,我不认为。在用户从服务器返回响应之前,用户很可能点击另一个视图。因此,我需要立即设置“聚焦”属性,以便我知道在单击下一个视图时忽略该视图。 – threejeez 2012-08-01 21:23:30

+0

关于等待参数的另一件事情:在这种情况下,服务器获得更新的速度并不重要;所有重要的是它按顺序到达那里。因此,对于这个模型,我重写了同步函数并实现了一次发送一个请求的ajax队列。 js代码可能会在更改事件被触发之前等待很长时间。 – threejeez 2012-08-01 21:32:22

+0

我关于'wait'的观点并不是针对最终代码---而是指向我们实际发生的事情。所以Firebug显示ajax成功?如果您发布“工作”小提琴,使用HTML&all ..it可能更容易看到发生了什么。 – EBarr 2012-08-01 21:51:20