В прошлой статье был описан фреймворк Angular.JS. И конечно же уже давно в воздухе висит вопрос “как там дела в других фреймворках?”. Вот перехожу к разбору BackBone. Хотя формально Backbone – это библиотека, а не фреймворк.
На примерах изучать все гораздо веселее, поэтому давайте разберем крохотный пример, в котором показывается реализация списка книг.
HTML-код примера совсем простой. Здесь пара кнопок и место под будущий список.
<body>
<div class="main">
<input id="addButton" type="button" value="Add one more book" />
<input id="changeButton" type="button" value="Update first book" />
<div>
<ul id="bookList"></ul>
</div>
</div>
</body>
А вот дальше начинается BackBone. Создаем модель.
// Модель книги
var Book = Backbone.Model.extend({
defaults: {
ID: "",
BookName: ""
},
idAttribute: "ID"
});
// Коллекция моделей книги (список книг)
var BooksCollection = Backbone.Collection.extend({
model: Book
});
Здесь вроде бы все интуитивно понятно. Модель Book создается через Backbone.Model.extend(), а через Backbone.Collection.extend() создается коллекция моделей Book.
Далее переходим к созданию видов. Понадобится сделать 2 вида. Первый – отображение одной книги, а второй – отображение списках (коллекции) книг.
// View для книги
var bookView = Backbone.View.extend({
tagName: 'li',
model: Book,
initialize: function() {
// Слушаем обновления модели (события изменения)
this.listenTo(this.model, 'change', this.render);
},
render: function (){
this.$el.html('<li>' + this.model.get('BookName') + '</li>');
return this;
}
});
// View для коллекции книг
var bookListView = Backbone.View.extend({
model: BooksCollection,
initialize: function() {
// Слушаем обновления модели (события добавления)
this.listenTo(this.model, 'add', this.modelUpdated);
},
modelUpdated: function() {
this.render();
},
render: function() {
this.$el.html('');
for(var i = 0; i < this.model.length; ++i) {
// Создаем экземпляр вида для каждой книги
var tBookView = new bookView({model: this.model.at(i)});
// Добавляем вид книги в вид списка книг
this.$el.append(tBookView.$el);
// Отрисовывем вид списка
tBookView.render();
}
return this;
}
});
Виды создаются через Backbone.View.extend(). Вид связывается с моделью через свойство model. Для отрисовки вида служит метод render(). В первом случает этот метод создает один пункт списка, а во втором в цикле вызывается одноименный метод первого вида.
В методах initialize() мы производим привязку обработчиков событий моделей. В виде связанном с экземпляром модели книги мы обрабатываем событие change, а в виде для списка книг обрабатываем add. Это нужно для будущей работы кнопок управления списком.
И наконец, логика нашего простого приложения.
$(document).ready(function () {
// Создаем несколько экземпляров модели (книг)
var book1 = new Book({ ID: 1, BookName: "Book 1" });
var book2 = new Book({ ID: 2, BookName: "Book 2" });
var book3 = new Book({ ID: 3, BookName: "Book 3" });
var book4 = new Book({ ID: 4, BookName: "Book 4" });
var book5 = new Book({ ID: 5, BookName: "Book 5" });
// Добавляем книги в модель
var bookCollection = new BooksCollection([book1, book2, book3, book4, book5]);
// Отображаем список книг
bookList = new bookListView({ el: $("#bookList"), model: bookCollection });
bookList.render();
// Привязываем события к кнопкам
$('#addButton').click(
function () {
var i = bookCollection.length + 1;
var newBook = new Book({ID: i, BookName: 'yet another book_' + i});
bookCollection.add(newBook);
}
);
$('#changeButton').click(
function () {
book1.set('BookName', book1.get('BookName') + '_updated');
}
);
});
Думаю, что по комментариям в коде понятен принцип работы. Здесь видно, что в обработчиках кликов по кнопках происходит работа с экземплярами моделей. А на изменения в моделях, как мы видим реагируют наши виды.
Вы можете скачать пример и попробовать работу приложения.
Как можно видеть, так же как и с Angular, с помощью Backbone можно увязать изменения модели с отображением внешнего вида. Однако в Backbone нужно будет описывать обработку событий для модели. В то время, как Angular делает это более менее самостоятельно опираясь на атрибут ng-model.
Здесь видно, что BackBone низкоуровневый. Здесь придется многое писать руками из того, что в Angular работает само. Но зато при более низкоуровневом подходе у нас больше контроля.
Что именно выбрать, я думаю, будет зависеть от конкретной задачи.
Конечно же возможности BackBone не заканчиваются тем, что описано выше. В Backbone так же, как и в Angular, можно прописывать и правила роутинга, чтобы получить правильные URL, о которых говорилось в прошлой статье. Есть возможность описывать правила валидации модели. Так же есть множество библиотек, которые можно подключить к BackBone для расширения его функционала. Этим в той же мере не может похвастаться Angular. Так что не все так однозначно.
Вот пока что и все. В следующих статьях мы продолжим знакомство с различными JS фреймворками и узнаем не мало интересного.