Backbone.js — это легковесный JavaScript-фреймворк, обеспечивающий структурированность клиентского кода за счёт разделения логики на модели, коллекции, представления (views) и роутеры. Основная цель Backbone — поддержка MVC-подхода (Model-View-Controller) в браузерных приложениях, где модели управляют данными, представления — отображением, а роутеры — навигацией.
Ключевым элементом Backbone является обеспечение синхронизации данных и интерфейса. Модели Backbone умеют реагировать на изменения своих атрибутов и уведомлять представления о необходимости обновления отображения. Это упрощает управление состоянием приложения и предотвращает прямое вмешательство в DOM.
Модель (Backbone.Model) представляет отдельный объект данных с набором атрибутов. Она предоставляет методы для чтения, записи и валидации данных:
var Task = Backbone.Model.extend({
defaults: {
title: '',
completed: false
},
toggle: function() {
this.set('completed', !this.get('completed'));
}
});
var myTask = new Task({ title: 'Изучить Backbone' });
myTask.toggle();
console.log(myTask.get('completed')); // true
Коллекция (Backbone.Collection) — это упорядоченный набор моделей, обеспечивающий удобную работу с группами объектов. Коллекции поддерживают методы фильтрации, сортировки и синхронизации с сервером.
var TaskList = Backbone.Collection.extend({
model: Task
});
var tasks = new TaskList([
{ title: 'Изучить Backbone', completed: false },
{ title: 'Написать учебник', completed: false }
]);
Представление (Backbone.View) связывает модель или коллекцию с DOM. Основная задача представления — отрисовка данных и обработка событий пользователя. В Backbone активно используется шаблонизация, которая позволяет отделить логику от разметки.
Простейший пример:
var TaskView = Backbone.View.extend({
tagName: 'li',
template: _.template('<%- title %>'),
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
var taskView = new TaskView({ model: myTask });
$('#task-list').append(taskView.render().el);
Здесь используется метод _.template из библиотеки
Underscore.js, которая идёт в комплекте с Backbone. Метод
toJSON() конвертирует модель в простой объект, пригодный
для шаблона.
Ключевое преимущество шаблонов — динамическое обновление представления при изменении модели:
myTask.on('change', function() {
taskView.render();
});
Backbone реализует собственную систему событий через методы
on, off и trigger. Модели и
коллекции могут уведомлять представления о любых изменениях, а
представления — реагировать на действия пользователя.
Пример связывания события с DOM:
var TaskView = Backbone.View.extend({
events: {
'click .toggle': 'toggleTask'
},
toggleTask: function() {
this.model.toggle();
}
});
Это позволяет создать двустороннюю связь: изменения модели обновляют интерфейс, а действия пользователя изменяют модель.
Роутер (Backbone.Router) управляет изменением URL и позволяет реализовать одностраничные приложения (SPA). Он связывает адрес с функцией обработки:
var AppRouter = Backbone.Router.extend({
routes: {
'tasks/:id': 'viewTask',
'tasks': 'listTasks'
},
viewTask: function(id) {
console.log('Просмотр задачи с ID:', id);
},
listTasks: function() {
console.log('Список всех задач');
}
});
var router = new AppRouter();
Backbone.history.start();
Использование роутера позволяет сохранять состояние интерфейса в URL, поддерживать переходы между видами без полной перезагрузки страницы и облегчает интеграцию с браузерной навигацией.
Backbone поддерживает RESTful-синхронизацию через
метод fetch, save и destroy.
Модели и коллекции могут автоматически взаимодействовать с сервером
через AJAX-запросы:
myTask.save(); // POST или PUT в зависимости от наличия id
tasks.fetch(); // GET для получения списка задач
Это упрощает интеграцию с API и делает клиентскую часть приложения максимально независимой от ручного написания AJAX-запросов.
Типичное Backbone-приложение строится следующим образом:
Такое разделение позволяет создавать масштабируемые, поддерживаемые и структурированные клиентские приложения, где каждая часть отвечает за свою зону ответственности, а шаблонизация обеспечивает чистую и понятную связь между данными и интерфейсом.