Подтвердить что ты не робот

Backbone.js: изменить не стрелять на model.change()

Я столкнулся с проблемой "событие изменения не срабатывает" на Backbone.js =/

Здесь мой взгляд на модель пользователя:

    window.UserView = Backbone.View.extend({

        ...

        initialize: function()
        {
            this.model.on('destroy', this.remove, this);

            this.model.on('change', function()
            {
               console.log('foo');
            });
        },

        render: function(selected)
        {
            var view = this.template(this.model.toJSON());

            $(this.el).html(view);

            return this;
        },

        transfer: function(e)
        {                
            var cas = listofcas;

            var transferTo = Users.getByCid('c1');
            var transferToCas = transferTo.get('cas');

            this.model.set('cas', cas);
            console.log('current model');
            console.log(this.model);

            //this.model.change();
            this.model.trigger("change:cas");
            console.log('trigger change');

            transferTo.set('cas', transferToCas);
            console.log('transferto model');
            console.log(transferTo);

            //transferTo.change();
            transferTo.trigger("change:cas");
            console.log('trigger change');

        }

    });

Здесь модель пользователя:

window.User = Backbone.Model.extend({

        urlRoot: $('#pilote-manager-app').attr('data-src'),

        initialize: function()
        {
            this.set('rand', 1);
            this.set('specialite', this.get('sfGuardUser').specialite);
            this.set('name', this.get('sfGuardUser').first_name + ' ' + this.get('sfGuardUser').last_name);
            this.set('userid', this.get('sfGuardUser').id);
            this.set('avatarsrc', this.get('sfGuardUser').avatarsrc);
            this.set('cas', new Array());

            if (undefined != this.get('sfGuardUser').SignalisationBouclePorteur) {

                var cas = new Array();

                _.each(this.get('sfGuardUser').SignalisationBouclePorteur, function(value)
                {
                    cas.push(value.Signalisation);
                });

                this.set('cas', cas);

            }
        }
    });

В модели пользователя существует атрибут "cas", который представляет собой массив объектов.

Я читаю в других разделах, которые изменяют события, не являются огнем на model.set, если атрибуты не являются значениями.

Итак, я пытаюсь инициировать непосредственно событие изменения с помощью метода model.change(). Но у меня нет записи "foo" в моей консоли...

4b9b3361

Ответ 1

Я новичок в позвоночнике, и у меня была такая же проблема.

После некоторых исследований я нашел несколько сообщений, которые проливают немного больше света на то, почему это происходит, и в конечном итоге все стало иметь смысл:

Вопрос 1

Вопрос 2

Основная причина связана с понятием равенства ссылок и равенства set/member. Похоже, что в значительной степени ссылочное равенство является одним из основных методов, используемых основой, чтобы выяснить, когда изменился атрибут.

Я нахожу, что если я использую методы, которые генерируют новую ссылку, такую ​​как Array.slice() или _.clone(), событие изменения распознается.

Так, например, следующий код не вызывает событие, потому что я изменяю тот же массив:

this.collection.each(function (caseFileModel) {
    var labelArray = caseFileModel.get("labels");
    labelArray.push({ Key: 1, DisplayValue: messageData });
    caseFileModel.set({ "labels": labelArray });
});

Пока этот код вызывает событие:

this.collection.each(function (caseFileModel) {
    var labelArray = _.clone(caseFileModel.get("labels")); // The clone() call ensures we get a new array reference - a requirement for the change event
    labelArray.push({ Key: 1, DisplayValue: messageData });
    caseFileModel.set({ "labels": labelArray });
});

ПРИМЕЧАНИЕ. В соответствии с Underscore API, _.clone() копирует определенные вложенные элементы по ссылке. Корневой/родительский объект клонируется, поэтому он отлично работает для магистрали. То есть, если ваш массив очень прост и не имеет вложенных структур, например. [1, 2, 3].

Хотя мой улучшенный код выше вызвал событие изменения, следующее не произошло, потому что в моем массиве содержались вложенные объекты:

var labelArray = _.clone(this.model.get("labels"));
_.each(labelArray, function (label) {
    label.isSelected = (_.isEqual(label, selectedLabel));
});
this.model.set({ "labels": labelArray });

Теперь почему это имеет значение? После отладки очень осторожно, я заметил, что в моем итераторе я ссылался на тот же объект, что и опорная магистраль. Другими словами, я случайно потянулся к внутренности моей модели и слегка перевернулся. Когда я вызывал setLabels(), позвоночник правильно распознал, что ничего не изменилось, поскольку он уже знал, что я перевернул этот бит.

Оглянувшись еще немного, люди, похоже, обычно говорят, что глубокие операции копирования в javascript - настоящая боль - ничего не сделано для этого. Поэтому я сделал это, и это сработало для меня - общая применимость может отличаться:

var labelArray = JSON.parse(JSON.stringify(this.model.get("labels")));
_.each(labelArray, function (label) {
    label.isSelected = (_.isEqual(label, selectedLabel));
});
this.model.set({ "labels": labelArray });

Ответ 2

Интересно. Я бы подумал, что .set({cas:someArray}) уволил бы событие изменения. Как вы сказали, это не похоже, и я не могу заставить его стрелять с помощью .change() НО, я могу заставить события работать, если я просто делаю model.trigger('change') или model.trigger('change:attribute')

Это позволит вам запускать событие изменения без взлома случайных атрибутов.

Если кто-то может объяснить, что происходит с событиями, Backbone и этим кодом, это поможет мне чему-то научиться... Вот какой-то код.

Ship = Backbone.Model.extend({
    defaults: {
        name:'titanic',
        cas: new Array()
    },
    initialize: function() {
        this.on('change:cas', this.notify, this);
        this.on('change', this.notifyGeneral, this);
    },
    notify: function() {
        console.log('cas changed');
    },
    notifyGeneral: function() {
        console.log('general change');
    }
});

myShip = new Ship();

myShip.set('cas',new Array());
    // No event fired off

myShip.set({cas: [1,2,3]});  // <- Why? Compared to next "Why?", why does this work?
    // cas changed
    // general change

myArray = new Array();
myArray.push(4,5,6);

myShip.set({cas:myArray});  // <- Why?
    // No event fired off
myShip.toJSON();
    // Array[3] is definitely there

myShip.change();
    // No event fired off

Интересная часть, которая может вам помочь:

myShip.trigger('change');
    // general change
myShip.trigger('change:cas');
    // cas changed

Я нахожу это интересным, и я надеюсь, что этот ответ также породит некоторое проницательное объяснение в комментариях, которых у меня нет.