2012-10-02 89 views
0

由於某些奇怪的原因,當我在模型驗證中返回字符串時,模型仍然設置屬性。這裏是我的代碼驗證碼:Backbone.js在驗證失敗時仍然設置模型屬性

Model = Backbone.Model.extend({ 
    validate: function(attributes){ 
     var tax = attributes.tax; 

     if(tax.amount < 0.0 || typeof tax.amount !== "number"){ 
      return "The tax amount cannot be negative and must be a number."; 
     } 
    }, 
    defaults: { 
     "tax": { 
      "amount": 100 
     } 
    }, 
    setTax: function(amount){ 
     var tax = this.get("tax"); 
     tax.amount = amount; 
     this.set("tax", tax); 
    } 
}) 

我那麼有模型偵聽錯誤事件和控制檯登錄它通過:正在打印

model = new Model(); 

    View = Backbone.View.extend({ 
     initialize: function(){ 
      this.model.on('error', function(model, error){ 
       console.log("ERROR: " + error); 
      }) 
     } 
    }); 
    view = new View({model: model}); 
    view.model.setTax(-100); 

控制檯日誌,但由於某種原因模型仍在設置該屬性。有什麼我需要返回到沒有模型設置屬性?根據Backbone.js碼頭,如果你從驗證中返回任何東西,那麼它假設不設置屬性。我使用Backbone.js的版本0.9.2

回答

3

你的問題就在這裏:

var tax = this.get("tax"); 

get方法基本上沒有return this.attributes[attr]tax屬性是一個對象,其結果是,你var tax和型號的this.attributes.tax是一回事。所以,當你說tax.amount = amount時,你實際上是直接編輯模型的attributes中的tax

當可變屬性(即不是數字,字符串和布爾其他任何東西)工作,你需要改變它們之前進行復印:

setTax: function(amount) { 
    var tax = _(this.get("tax")).clone(); 
    tax.amount = amount; 
    this.set("tax", tax); 
} 

進行復印也可以防止骨幹來自以爲你set通話實際上並沒有做任何事情。如果您不像上面那樣克隆tax,則不會在模型上觸發更改事件,這可能不是您想要的。

幾個例子(打開你的控制檯請):

+0

謝謝您的回答!但是,我的實際模型比我給出的模型複雜得多。例如,我縮短了它。我試過克隆,但我仍然遇到同樣的問題。克隆似乎只創建您正在克隆的模型的第一級屬性的副本。我分叉你的小提琴演示這個:http://jsfiddle.net/NeHkm/。我假設解決這個問題的唯一方法是克隆對象的每個屬性? –

+0

是的,根據Underscore.js文檔,它顯示克隆功能只是簡單地:創建對象的淺拷貝克隆。任何嵌套的對象或數組將被引用複製,而不是重複。 –

+0

@PhillipWhisenhunt:是的,'_.clone'只做一個淺拷貝,你可以使用['$ .extend'](http://api.jquery.com/jQuery.extend/)做一個深層拷貝。但是,如果你的屬性很複雜,你可能想重新考慮你的數據結構。 –