Я довольно новичок в магистральной сети, и у меня возникла та же проблема.
После некоторых исследований я обнаружил несколько постов, которые проливают немного больше света на то, почему это происходит, и в конечном итоге на вещи.начал иметь смысл:
Вопрос 1
Вопрос 2
Основная причина связана с понятием ссылкиравенство против множества / членства.Похоже, что в значительной степени равенство ссылок является одним из основных методов, используемых магистралью для определения того, когда атрибут изменился.
Я считаю, что если я использую методы, которые генерируют новую ссылку, такую как 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 });
});
ПРИМЕЧАНИЕ. В соответствии с API Underscore *1023* _.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 (), backbone правильно распознал, что ничего не изменилось, потому что он уже знал Я перевернул этот бит.
После осмотра еще, люди, как правило, говорят, что операции глубокого копирования в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 });