更新阵列时模型的更改事件不会触发?

时间:2011-12-13 15:15:10

标签: javascript jquery backbone.js coffeescript

使用backbone.js ...

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

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

这会完美更新模型,但不会触发更改事件。有谁知道为什么从看到我发布的内容?

编辑:

我添加了这个并触发了更改事件:

@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

5 个答案:

答案 0 :(得分:8)

布莱恩关于原因的答案很棒!

想要提供另一种获取所需内容的方法,而不是将其清零或克隆数组。

只需自己手动触发更改:

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

答案 1 :(得分:7)

由于您正在设置引用的对象,请使用_.clone()

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

由于您不再使用引用的对象/数组来设置自身,因此如果更改事件已更改,它将触发更改事件。

答案 2 :(得分:6)

问题是您使用现有值设置值。看一下源代码:

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

当你调用set时,它有一个保护子句,以确保你没有设置相同的值(以避免事件循环)。在您的情况下,您将获取阵列,修改它并再次设置它,这不会触发您的事件。

当然,当你set test: {}时,它是一个带有新对象的新项目,因此会再次触发。如果你真的想要触发事件,你可以将它设置为null,然后将其设置为空数组,然后再次设置为填充的数组...

答案 3 :(得分: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()方法并且属性已更新时)。

这样做或手动调用事件之间并没有什么区别,这只是个人偏好的问题。

答案 4 :(得分:1)

你能考虑使用Backbone集合而不是数组,然后绑定到更改该集合中的事件吗?