Application structure и organization

Backbone.js предоставляет лёгкий каркас для построения структурированных веб-приложений, основанных на модели MVC (Model-View-Controller) или, точнее, на паттерне MVP (Model-View-Presenter). Основная цель фреймворка — разделение данных, представления и логики приложения, что облегчает поддержку, масштабирование и тестирование кода.


Модели (Models)

Модель отвечает за управление данными и бизнес-логикой приложения. Backbone.Model предоставляет методы для:

  • Хранения данных: модели хранят свойства объекта и позволяют устанавливать их через set и получать через get.
  • Валидации: метод validate позволяет проверять корректность данных перед их установкой.
  • Событий: модели поддерживают систему событий, что позволяет подписываться на изменения данных через on и off.

Пример создания модели:

var Task = Backbone.Model.extend({
    defaults: {
        title: '',
        completed: false
    },
    validate: function(attrs) {
        if (!attrs.title) {
            return "Title cannot be empty";
        }
    }
});

Модель может взаимодействовать с сервером через встроенный Backbone.sync, поддерживая CRUD-операции (create, read, update, delete) и RESTful API.


Коллекции (Collections)

Коллекция (Backbone.Collection) — это упорядоченный набор моделей одного типа. Она обеспечивает:

  • Манипуляции с множеством моделей: добавление, удаление, сортировку и фильтрацию.
  • События коллекции: add, remove, reset и sort позволяют автоматически обновлять представления при изменении данных.
  • Синхронизацию с сервером: коллекция может загружать данные с API и обновлять модели.

Пример коллекции:

var TaskList = Backbone.Collection.extend({
    model: Task,
    comparator: 'title'
});

var tasks = new TaskList();
tasks.add({ title: "Finish project" });
tasks.add({ title: "Write documentation" });

Представления (Views)

Представление (Backbone.View) отвечает за отображение данных модели и обработку пользовательских событий. Основные функции:

  • Рендеринг данных модели: обновление DOM при изменении модели или коллекции.
  • Обработка событий: связывание событий интерфейса с методами представления через объект events.
  • Поддержка вложенных представлений: для построения сложных интерфейсов.

Пример представления:

var TaskView = Backbone.View.extend({
    tagName: 'li',
    events: {
        'click .toggle': 'toggleCompleted'
    },
    initialize: function() {
        this.listenTo(this.model, 'change', this.render);
    },
    render: function() {
        this.$el.html(this.model.get('title'));
        this.$el.toggleClass('completed', this.model.get('completed'));
        return this;
    },
    toggleCompleted: function() {
        this.model.set('completed', !this.model.get('completed'));
    }
});

Маршрутизация (Router)

Маршрутизатор (Backbone.Router) управляет состоянием приложения через URL. Он позволяет:

  • Определять маршруты: связывать URL с функциями обработчика.
  • Поддерживать навигацию без перезагрузки страницы: используя pushState или hash фрагменты.
  • Инициализировать представления и модели на основе URL.

Пример маршрутизатора:

var AppRouter = Backbone.Router.extend({
    routes: {
        'tasks/:id': 'showTask',
        'tasks': 'listTasks'
    },
    showTask: function(id) {
        var task = tasks.get(id);
        var view = new TaskView({ model: task });
        $('#app').html(view.render().el);
    },
    listTasks: function() {
        var listView = new TaskListView({ collection: tasks });
        $('#app').html(listView.render().el);
    }
});

Организация структуры проекта

Для больших приложений Backbone.js рекомендует разделять код по функциональным слоям:

  1. models/ — модели приложения. Каждая модель описывает отдельный объект данных.
  2. collections/ — коллекции моделей. Обеспечивают работу с набором объектов.
  3. views/ — представления и их подмодули. Рендеринг и управление пользовательским интерфейсом.
  4. routers/ — маршрутизаторы приложения, связывающие URL с логикой.
  5. templates/ — шаблоны для рендеринга данных в представлениях, обычно с использованием Underscore.js или другого шаблонизатора.
  6. app.js — точка входа приложения, инициализация коллекций, моделей и маршрутов.

Структура файлов может выглядеть так:

app/
├── models/
│   └── task.js
├── collections/
│   └── taskList.js
├── views/
│   ├── taskView.js
│   └── taskListView.js
├── routers/
│   └── appRouter.js
├── templates/
│   └── taskTemplate.html
└── app.js

Коммуникация между компонентами

Backbone.js опирается на события для связи компонентов:

  • Модель или коллекция генерирует события при изменении данных.
  • Представления подписываются на события и обновляют интерфейс.
  • Использование глобального события через объект Backbone.Events позволяет связывать независимые компоненты.

Пример глобального события:

var dispatcher = _.extend({}, Backbone.Events);

dispatcher.on('task:added', function(task) {
    console.log('New task added:', task.get('title'));
});

tasks.on('add', function(task) {
    dispatcher.trigger('task:added', task);
});

Такой подход позволяет избегать тесной связности компонентов и упрощает масштабирование приложения.


Организация больших приложений

Для сложных проектов рекомендуется:

  • Модульность кода: использовать AMD, CommonJS или ES6 модули для управления зависимостями.
  • Чёткое разделение ответственности: каждая модель, представление и коллекция решают строго ограниченную задачу.
  • Повторное использование компонентов: общие представления, шаблоны и утилиты выносятся в отдельные модули.
  • Тестируемость: благодаря разделению моделей, коллекций и представлений их можно легко покрывать юнит-тестами.

Эта структура позволяет Backbone.js оставаться лёгким и гибким инструментом для разработки масштабируемых веб-приложений с чистым и управляемым кодом.