主干js中的集合不允许您使用set
属性,但我经常发现需要存储有关集合的一些元信息。设置该信息的最佳位置在哪里?
答案 0 :(得分:43)
只需.extend
具有元数据存储功能的集合。
var MyCollection = Backbone.Collection.extend({
initialize: function() {
...
this._meta = {};
},
model: ...
meta: function(prop, value) {
if (value === undefined) {
return this._meta[prop]
} else {
this._meta[prop] = value;
}
},
});
var collection = new MyCollection();
collection.add(someModels);
collection.meta("someProperty", value);
...
var value = collection.meta("someProperty");
存储特定元数据的位置可能更好,但这完全取决于元数据的内容。
用于存储扩展集合构造函数的泛型元数据,并使用一种方法来处理它应该有效。
要小心,如果需要从服务器存储和加载此元数据,那么您手头有更大的任务。
答案 1 :(得分:16)
最好以完全按照预期的方式使用Collection:作为一组模型。 (Julien已经在OP上发表了这个评论,我想解释为什么我认为他是对的)
假设您正在考虑Book(模型)的库(集合),如Backbone的文档示例中所示。您有关于要存储的库的元信息(例如此图书库所在的地址)是有道理的。
诀窍不是将其视为元信息。你有一个拥有很多属性的库,其中一个属性是它的书籍集。
var Book = Backbone.Model.extend({
title: "Moby Dick"
});
var Collection = Backbone.Collection.extend({
model: Book
});
var Library = {
address: '45th Street',
collection: Collection
};
在这个例子中,我将Library定义为一个普通的JavaScript对象。显然你也可以让Library成为一个模型,这样它就拥有了所有的Backbone铃声和口哨声。 我的观点是,你需要以一种更现实的方式表现现实,退一步看看你想要分配给Collection的额外属性实际上是一级对象的兄弟属性:在这种情况下的库
答案 2 :(得分:7)
我已经通过事件触发升级了Raynos的方法,因此我们可以绑定到集合的属性更新。
cls.groups = Backbone.Collection.extend({
// ...
// Reference to this collection's model.
model: cls.group,
initialize: function() {
this._attributes = {}
},
// Extend collection with ability to store attributes and trigger events on attributes changing
attr: function(prop, value) {
if (value === undefined) {
return this._attributes[prop]
} else {
this._attributes[prop] = value;
this.trigger('change:' + prop, value);
}
},
// ...
});
cls.group = Backbone.View.extend({
// ...
initialize: function() {
// Catching attribute update
app.groups.on('change:selected', function(value) {
// ...
}, this);
},
// ...
events: {
'click' : function(e) {
// Set collection meta attribute on model's view click event
app.groups.attr('selected', this.model.cid);
}
}
// ...
});
答案 3 :(得分:3)
使用@Raynos解决方案的函数meta
只有一个参数对我不起作用。所以我使用了以下代码:
var MyCollection = Backbone.Collection.extend({
initialize: function() {
this._meta = {};
},
put: function(prop, value) {
this._meta[prop] = value;
},
get: function(prop) {
return this._meta[prop];
}
});
var collection = new MyCollection();
collection.put("someProperty", 12);
alert(collection.get("someProperty"));
希望它会有所帮助。
答案 4 :(得分:0)
我已经阅读了其他答案和评论,尽管我很欣赏将模型包装到模型中绝对是最干净的方法,但我发现它有99.9%的时间绝对过大。骨干网为IMO提供了initialize
钩子。
const FooCollection = Backbone.Collection.extend({
initialize: function(models, attributes) {
attributes.log && console.log('foo!'); // Or set attributes on 'this', etc
}
});
// Passing null for first arg, which is optionally an array of models
// to initialize the collection with
const fooCollection = new FooCollection(null, { log: true } );
这样做已经很多年了,从未遇到任何问题/缺点。