请在下面找到我能理解的最简洁的复制 Backbone 应用程序中导致Collection
进入内部混乱状态的一系列步骤。
可以在此JSFiddle 中找到工作副本。
它展示的是collection
保持对remove()
-ed Model
的内部( _byId
)引用。 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 更改为value == null 时,集合没有一些特殊的逻辑,请检查第 1183 行。
您也可以更改未设置以设置_null_ 或 _undefined_。 this.model.set('id', null);
PS:我认为您永远不需要将模型 ID 设置为 null 或未定义,这是反模式。
是的 - 你永远不应该这样做,但这仍然是一个错误。
我们应该通过确保如果id
从一个值变为null
,我们首先delete this._byId[id]
。
如果您在不使用事件的情况下从集合中删除模型,它会按预期工作。 问题出在_onModelEvent
,它检查事件名称是否为change
,而在这种情况下发送的实际事件名称为change:id
。
最有用的评论
是的 - 你永远不应该这样做,但这仍然是一个错误。
我们应该通过确保如果
id
从一个值变为null
,我们首先delete this._byId[id]
。