【问题标题】:Model's change event won't fire when updating an array?更新数组时不会触发模型的更改事件?
【发布时间】:2012-01-19 11:08:12
【问题描述】:

使用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

【问题讨论】:

  • 数组是否被填充?
  • 是的,模型更新正常,并且数组正确填充到模型属性中。

标签: javascript jquery backbone.js coffeescript


【解决方案1】:

在更改对象或数组时,另一种方法是在设置新的更新值之前静默取消设置属性。像这样的:

(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() 方法并且属性已更新时)。

执行此操作或手动调用事件并没有真正的区别,这只是个人喜好问题。

【讨论】:

  • 我更喜欢这个选项 - 这样 Backbone 会使用默认参数触发所有事件变体(changechange:arrayProp),因此不会破坏任何侦听器。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    您是否可以考虑使用 Backbone 集合而不是数组,然后绑定以更改该集合中的事件?

    【讨论】:

      【解决方案4】:

      Brian 关于原因的回答太棒了!

      想要提供另一种方法来获得你想要的东西,而不是把它清空或克隆数组。

      只需自己手动触发更改:

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

      【讨论】:

      • 如果你有一个特别大的阵列克隆,这是一个糟糕的选择。这更有意义。
      【解决方案5】:

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

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

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

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

      【讨论】: