Ниже вы можете найти кратчайшее воспроизведение, которое я смог понять, последовательности шагов в приложении Backbone, которое приводит к тому, что Collection
входит в состояние внутренней неразберихи.
Рабочую копию можно найти в этом JSFiddle .
Он демонстрирует, что collection
сохраняет внутреннюю ( _byId
) ссылку на remove()
-ed Model
. Этот Model
больше не является частью collection.models
, однако его все еще можно получить с помощью его (бывшего) id
.
var
MyView = Backbone.View.extend( {
initialize: function () {
this.model = new Backbone.Model( {
id: 'foo'
, foo: 'bar'
} );
this.collection = new Backbone.Collection( this.model );
this.listenTo( this.model, 'change:id', function ( model, id ) {
if ( id == null ) {
this.collection.remove( model );
}
} );
this.model.unset( 'id' );
$('#models' ).val( JSON.stringify( this.collection.models ));
$('#_byId' ).val( JSON.stringify( this.collection._byId ));
$('#get-foo').val( JSON.stringify( this.collection.get( 'foo' )));
}
})
, foo = new MyView()
;
Хм, интересно. Когда мы добавляем модель в коллекцию, __byId_ добавляет два свойства: model.id и model.cid, их ссылку на модель. Ошибка в строке 1134, id === undefined , но __byId_ содержит model.id - _'foo'_.
Коллекция не имеет особой логики при изменении model.id на значение == null , проверьте строку 1183.
Также вы можете изменить незаданы для множества _null_ или _undefined_. this.model.set ('идентификатор', ноль);
PS: Я думаю, вам никогда не нужно устанавливать идентификатор модели на null или undefined, это антипаттерн.
Да, вы никогда не должны этого делать, но это все еще ошибка.
Мы должны исправить это, убедившись, что если id
меняется со значения на null
, сначала мы delete this._byId[id]
.
Если вы удалите модель из коллекции без использования события, она будет работать должным образом. Проблема заключается в _onModelEvent
который проверяет, является ли имя события change
, когда фактическое имя события, отправляемое в этом случае, - change:id
.
Самый полезный комментарий
Да, вы никогда не должны этого делать, но это все еще ошибка.
Мы должны исправить это, убедившись, что если
id
меняется со значения наnull
, сначала мыdelete this._byId[id]
.