Событие изменения модели не сработает при обновлении массива? - PullRequest
5 голосов
/ 13 декабря 2011

Использование 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 ]

8 голосов
/ 13 декабря 2011

Ответ Брайана о причине удивителен!

Хотел представить другой способ получить то, что вам нужно, вместо обнуления или клонирования массива.

Просто вручную запустите изменение:

addIndex = (index) =>
    array = @model.get('array')
    array.push index
    @model.trigger('change:array',@model, array)
7 голосов
/ 20 декабря 2011

Поскольку вы устанавливаете ссылочный объект, используйте _.clone().

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

Поскольку вы больше не используете объект / массив, на который указывает ссылка, для установки самого себя, оно вызовет событие change, если оно изменилось.

6 голосов
/ 26 сентября 2013

Другой способ пойти при изменении объектов или массивов, это незаметно сбросить свойство перед установкой нового обновленного значения.Примерно так:

(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() и свойство обновлено).

На самом деле нет никакой разницы между выполнением этого или вызовом события вручную, это просто вопрос личных предпочтений.

6 голосов
/ 13 декабря 2011

Проблема в том, что вы устанавливаете значение с существующим значением.Взгляните на исходный код:

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

Когда вы звоните set, в нем есть пункт guard, чтобы убедиться, что вы не устанавливаете одно и то же значение (чтобы избежать циклов событий).В вашем случае вы получаете массив, модифицируете его и устанавливаете заново, что не будет вызывать ваше событие.

Конечно, когда вы set test: {}, это новый элемент с новым объектом,так что сработает снова.Если вы действительно хотите вызвать событие, вы можете установить его в null, затем установить его в пустой массив, а затем снова в заполненный массив ...

1 голос
/ 15 декабря 2011

Не могли бы вы рассмотреть возможность использования коллекции Backbone вместо массива, а затем связывание для изменения событий в этой коллекции?

...