2011-12-13 99 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

相关问题