Backbone.js предоставляет мощный механизм для организации данных с помощью моделей и коллекций. Одним из продвинутых подходов является использование вложенных коллекций, когда модель содержит коллекцию как одно из своих свойств. Этот подход позволяет создавать сложные структуры данных, поддерживать иерархию и удобно работать с множественными уровнями вложенности.
В Backbone.js модель описывается через Backbone.Model.
Если необходимо, чтобы модель содержала коллекцию, следует определить
это свойство и позаботиться о правильной инициализации.
Пример:
var Task = Backbone.Model.extend({
defaults: {
title: '',
completed: false
}
});
var TaskList = Backbone.Collection.extend({
model: Task
});
var Project = Backbone.Model.extend({
defaults: function() {
return {
name: '',
tasks: new TaskList()
};
},
initialize: function() {
// Обеспечение того, что при создании модели tasks будет коллекцией
if (!(this.get('tasks') instanceof TaskList)) {
this.set('tasks', new TaskList(this.get('tasks')));
}
}
});
В этом примере модель Project содержит коллекцию
TaskList в свойстве tasks. Метод
initialize гарантирует, что даже если при создании передан
массив объектов, он будет преобразован в полноценную коллекцию
Backbone.
Вложенные коллекции поддерживают все стандартные методы Backbone:
var project = new Project({ name: 'Website Redesign' });
project.get('tasks').add({ title: 'Create wireframes' });
project.get('tasks').add({ title: 'Develop frontend' });
console.log(project.get('tasks').length); // 2
Методы add, remove, reset и
другие работают на уровне вложенной коллекции так же, как на обычной
коллекции. Это позволяет управлять задачами проекта напрямую через
объект проекта.
Backbone поддерживает события на коллекциях и моделях. Для вложенных коллекций важно учитывать правильную привязку событий, чтобы изменения на уровне задач можно было отслеживать через модель проекта.
project.get('tasks').on('add', function(task) {
console.log('Добавлена задача:', task.get('title'));
});
project.get('tasks').on('change:completed', function(task) {
console.log('Задача выполнена:', task.get('title'));
});
var task = new Task({ title: 'Design logo' });
project.get('tasks').add(task);
task.set('completed', true);
В данном примере события add и
change:completed срабатывают для вложенной коллекции
tasks, обеспечивая реактивное обновление состояния
проекта.
При необходимости отправки данных на сервер или сохранения в
localStorage важно правильно сериализовать вложенные коллекции.
Backbone.js предоставляет метод toJSON, который рекурсивно
обрабатывает коллекции.
var jsonData = project.toJSON();
console.log(jsonData);
/*
{
name: 'Website Redesign',
tasks: [
{ title: 'Create wireframes', completed: false },
{ title: 'Develop frontend', completed: false },
{ title: 'Design logo', completed: true }
]
}
*/
Использование toJSON обеспечивает корректную структуру
данных для передачи на сервер, включая вложенные коллекции.
Для получения данных с сервера необходимо правильно обрабатывать
вложенные коллекции в методе parse:
var Project = Backbone.Model.extend({
defaults: function() {
return {
name: '',
tasks: new TaskList()
};
},
parse: function(response) {
if (response.tasks) {
this.get('tasks').reset(response.tasks);
delete response.tasks;
}
return response;
}
});
var project = new Project();
project.fetch({
url: '/projects/1',
success: function(model) {
console.log(model.toJSON());
}
});
Метод parse позволяет отделить данные коллекции от
остальных атрибутов модели, автоматически создавая вложенную коллекцию и
наполняя её элементами с сервера.
Вложенные коллекции можно комбинировать и создавать многоуровневые структуры. Например, проект может содержать задачи, а каждая задача — подзадачи:
var SubTask = Backbone.Model.extend({});
var SubTaskList = Backbone.Collection.extend({ model: SubTask });
var Task = Backbone.Model.extend({
defaults: function() {
return { title: '', completed: false, subTasks: new SubTaskList() };
},
initialize: function() {
if (!(this.get('subTasks') instanceof SubTaskList)) {
this.set('subTasks', new SubTaskList(this.get('subTasks')));
}
}
});
var TaskList = Backbone.Collection.extend({ model: Task });
Такая архитектура позволяет реализовать сложные приложения с глубокими зависимостями между данными и упрощает управление состоянием через Backbone.js.
initialize или defaults, чтобы избежать
проблем с сериализацией и событиями.parse при работе с данными с сервера для
корректной загрузки вложенных коллекций.Вложенные коллекции позволяют создавать структурированные, иерархические модели данных, делая Backbone.js гибким инструментом для построения клиентских приложений любой сложности.