我是骨干网的新手。
在对无法将我的一些模型添加到集合以及有时使用collection.get(id)
得到错误的模型感到困惑之后,我发现我的模型ID与主干cid发生了冲突。
我的型号id类似于"c7"或"c5e6"。而后面的"c7"则是主链自己的cid作为集合的第七个元素。
因此,如果我请求collection.get('c7')
并期望null
,那么我会得到主干赋予cid"c7"的元素。如果我添加一个id为"c7"的元素,我将永远无法用get("c7")
将其取回。
我想知道我是否是第一个遇到这个问题的人,我没有发现任何关于主干ID语法限制的信息,有办法解决这个问题吗?作为一种变通方法,我将把自己的id保存在一个自定义属性中,并且必须使用collection.where
而不是collection.get
。
有更好的主意吗?
如果查看Backbone源代码,您会发现模型中的cid
是由在构造函数中确定的
this.cid = _.uniqueId('c');
c是一个任意前缀,这意味着您可以通过重写_.uniqueId
(类似)来消除id的歧义
_._uniqueId = _.uniqueId;
_.uniqueId = function(prefix) {
if (prefix === 'c') {
prefix = 'cc';
}
return _._uniqueId(prefix);
};
在没有超控的情况下:http://jsfiddle.net/nikoshr/KmNSr/有了它:http://jsfiddle.net/nikoshr/KmNSr/1/
不幸的是,这看起来确实是一个没有真正解决方案的边缘案例问题。查看Backbone源,我们可以在Backbone.Collection.set
方法中看到,Backbone将您的ID及其内部CID混合在同一个对象中:
set: function(models, options) {
// ...
this._byId[model.cid] = model;
if (model.id != null) this._byId[model.id] = model;
// ...
return this;
},
_byId
对象包含导致问题的所有ID。这里是Backbone.Collection.get
方法:
get: function(obj) {
if (obj == null) return void 0;
return this._byId[obj.id != null ? obj.id : obj.cid || obj];
},
当您使用不存在的ID(您自己的ID)(如"c7")调用它时,return ...
行将变为return this._byId["c7"];
。由于_byId
引用了您和Backbone的ID,因此您将在预期null
时返回它们的条目。
尼科什在下面的答案中有一个很好的解决方案。