2011-12-13 181 views
5

使用Backbone.js的...更新數組時,模型的更改事件不會觸發?

@model.bind 'change',()-> console.log 'updated' 

addIndex = (index) => 
    array = @model.get('array') 
    array.push index 
    @model.set 
     array: array 

這完全更新模型,但不會觸發更改事件。有誰知道爲什麼看着我發佈的內容?

編輯:

我說這一點,它會觸發change事件:

@model.set 
    test: '' 

num = 0 
setInterval()=> 
    num++ 
    @model.set 
    test: num 
, 3000 

我說這一點,它不會觸發更改事件:

@model.set 
    test: [] 

num = 0 
setInterval()=> 
    console.log 'testupdate' 
    num++ 
    test = @model.get('test') 
    test.push num 
    @model.set 
     test: test 
, 3000 
+0

是數組得到填充? – Brian

+0

模型更新正常,數組正確填充到模型屬性中。 – fancy

回答

6

的問題是您正在使用現有值設置值。看看源代碼:

http://documentcloud.github.com/backbone/docs/backbone.html#section-33

當你調用set它有保護條款,以確保您沒有設置相同的值(以避免事件循環)。在你的情況下,你得到的數組,修改它,並再次設置,這將不會觸發你的事件。

當然,當你set test: {},這是一個新的對象,所以它會再次觸發。如果你真的想要觸發事件,你可以將它設置爲空,然後將其設置爲一個空陣列,然後再次將其設置爲組裝陣列...

8

Brian對於原因的回答很棒!

想通過另一種方式來獲得你想要的而不是將它清零或克隆數組。

只是自己手動觸發變化:

addIndex = (index) => 
    array = @model.get('array') 
    array.push index 
    @model.trigger('change:array',@model, array) 
+0

如果你有一個特別大的數組克隆它是一個糟糕的選擇。這樣做更有意義。 –

+0

使用此解決方案model.changed將不會更新。 – postnerd

1

你可以考慮使用一個骨幹集合,而不是一個數組,然後結合改變集中的事件?

7

由於您正在設置參考對象,請使用_.clone()

test = _.clone @model.get('test') 
test.push num 
@model.set test: test 

既然你不再使用引用的對象/數組來設置本身,它會如果它已經改變了觸發更改事件。

6

當更改對象或數組時,另一種方法是在設置新的更新值之前以靜默方式取消設置屬性。事情是這樣的:

(function() { 
    var arr, model = new Model(); 

    model.set("arrayProp", [1, 2, 3]); 
    arr = model.get("arrayProp"); 
    arr.push(4); 

    model.unset("arrayProp", { silent: true }); 
    model.set("arrayProp", arr); 
})(); 

通過取消道具時設置silent: true,更改事件纔會觸發一次(當set()方法被調用和物業已更新)。

這樣做或手動調用事件並沒有什麼區別,它只是個人偏好的問題。

+2

我更喜歡這個選項 - 這種方式Backbone使用默認參數觸發所有事件變體('change'和'change:arrayProp'),所以它不會破壞任何監聽器。 – joews

相關問題