Model's change event won't fire when updat

2019-05-03 01:44发布

Using backbone.js...

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

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

This updates the model perfectly but doesn't trigger the change event. Does anyone know why from looking at what I posted?

EDIT:

I added this and it triggers the change event:

@model.set
    test: ''

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

I added this and it doesn't trigger the change event:

@model.set
    test: []

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

5条回答
我只想做你的唯一
2楼-- · 2019-05-03 02:17

Could you consider using a Backbone collection instead of an array, and then binding to change events in that collection?

查看更多
Fickle 薄情
3楼-- · 2019-05-03 02:21

The problem is that you are setting the value with the existing value. Take a look at the source code:

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

When you call set it has a guard clause to make sure that you are not setting the same value (to avoid event loops). In your case, you are getting the array, modifying it, and setting it again, which will not trigger your event.

Of course, when you set test: {}, it is a new item with a new object, so it will trigger again. If you really want to trigger the event, you can set it to null, then set it to an empty array and then to the populated array again...

查看更多
Anthone
4楼-- · 2019-05-03 02:23

Another way to go, when changing objects or arrays, is to silently unset the property before setting the new updated value. Something like this:

(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 );
})();

By setting silent: true when unsetting the prop, the change event will only fire once (When the set() method is called and the property has been updated).

There isn't really a difference between doing this or manually calling the event, it's just a matter of personal preference.

查看更多
Deceive 欺骗
5楼-- · 2019-05-03 02:32

Brian's answer as to the reason is awesome!

Wanted to present another way to get what you want instead of nulling it out or cloning the array.

Just manually trigger the change yourself:

addIndex = (index) =>
    array = @model.get('array')
    array.push index
    @model.trigger('change:array',@model, array)
查看更多
我欲成王,谁敢阻挡
6楼-- · 2019-05-03 02:34

Since you're setting the referenced object, use _.clone().

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

Since you're no longer using the referenced object/array to set itself, it will fire the change event if it has changed.

查看更多
登录 后发表回答