#javascript #backbone.js
#javascript #backbone.js
Вопрос:
У меня есть следующая модель с вложенной коллекцией
var Mdl = Backbone.Model.extend({
initialize: function() {
// collection
this.col1 = new NestedCollection();
},
...
});
Я хотел бы отправить данные как для модели, так и для моделей в коллекции в одном запросе, выглядящем примерно так:
{
att1: val,
col1: [{obj1: val}, {...}]
}
Я не уверен в наилучшем способе передачи данных в запросе во вложенную коллекцию (col1). Я не могу сделать…
var Mdl = Backbone.Model.extend({
initialize: function() {
// collection
this.col1 = new NestedCollection(this.get('col1');
},
...
});
… поскольку во время инициализации вызывается функция синтаксического анализа модели, которая не была вызвана, что означает, что атрибут col1 пуст, другим решением, о котором я подумал, было прослушивание изменений в родительской модели, например…
model.bind("change:tags", function() {
model.col1.refresh(model.get('col1'));
});
однако это решение кажется немного тяжеловесным и потенциально может нарушить любой
this.col1.bind("add", function() {})
и
this.col1.bind("remove", function() {})
настройка функций в коллекции.
Есть ли у кого-нибудь представление об «официальном» способе сделать это?
Спасибо.
Ответ №1:
«Официальным» способом является переопределение метода parse:
http://documentcloud.github.com/backbone/#Model-parse
В вашем конкретном случае, что я, вероятно, сделал бы, так это в методе parse создайте вложенную коллекцию из данных col1, удалите ее из результатов, затем передайте результаты дальше. Затем Backbone преобразует остальные данные в свойства.
Я не пробовал это, поэтому я не уверен на 100%, что это работает:
parse: function(response) {
this.col1 = new NestedCollection(response.col1);
delete response.col1
return response
}
Редактировать: 28 ноября 2012
Харм указывает, что это, возможно, не лучший способ сделать это больше. Первоначальный ответ был написан довольно давно, и в исходном вопросе указывалось, что пользователь хотел, чтобы коллекция была свойством модели (не атрибутом), но Харм считает, что использование коллекции в качестве атрибута является более приемлемым способом сделать это в наши дни.
Сегодня вы могли бы использовать что-то вроде Backbone-Relational, чтобы обрабатывать большую часть этого материала за вас, или, если вы хотите сделать это самостоятельно, и иметь коллекцию в качестве атрибута модели, вы могли бы сделать что-то вроде:
Building = Backbone.Model.extend({
parse: function(response) {
console.log("Parse Called");
response.rooms = new Rooms(response.rooms);
return response;
}
});
Room = Backbone.Model.extend({});
Rooms = Backbone.Collection.extend({
model: Room
});
science_building = new Building();
science_building.fetch(
{success: function(model,resp) {console.log(resp);}}
);
С помощью ответа выборки модели, подобного:
{ id: 1,
name: "Einstein Hall",
rooms: [
{id:101, name:'Chem Lab'},
{id:201, name:'Physics Lab'},
{id:205, name:'Bio Lab'}
]
}
В результате получается модель построения, которая позволяет:
science_building.get('rooms').get(101).get('name') // ==> "Chem Lab"
Рабочий пример jsFiddle:http://jsfiddle.net/edwardmsmith/9bksp /
Комментарии:
1. Я не полностью согласен с этим решением.
parse()
должно вернуть кучу атрибутов. Теперь у этого есть какой-то странный побочный эффект установки чего-либо непосредственно в модели. Возможно, лучше заменить содержимое ключа коллекции на соответствующую базовую коллекцию.2. У меня не работает Fiddle — добавлен jsbin jsbin.com/fafulunexe/edit?html ,js, вывод
3. Обновленный fiddle с новыми источниками CDN для backbone и подчеркивания. Спасибо, что предупредили.