2. Что даёт?
• Наследование
• Модели (Models)
• Коллекции [Underscore JS]
• Представления (Views)
• Событийно‑ориентированные коммуникации
(Events)
• Персистентность (Sync)
– возможность прозрачного сохранения состояния своих объектов в
промежутках времени между запусками программ
• Маршрутизация и HTML5 pushState
• Потенциальная возможность тестирования
(Jasmine/QUnit/SimonJS)
3. Модели
• Модель ‑ это одна запись.
• Содержит интерактивные данные
• Реализует
– Конвертацию
– Валидацию
– Вычисление свойств
– Контроль доступа
• Реализуется посредством наследования стандартного класса
Backbone.Model
• Базовый класс набор необходимых и вспомогательных
методов для работы со свойствами (get/set, escape, has,
toJSON, fetch, isValid, validate, save и.т.п.)
4. Пример
var Photo = Backbone.Model.extend({
defaults: {
src: 'placeholder.jpg',
title: 'an image placeholder',
coordinates: [0,0]
},
initialize: function() {
this.on("change:src", function() {
var src = this.get("src");
console.log('Image source updated to ' + src);
});
},
changeSrc: function( source ) {
this.set({ src: source });
}
});
var somePhoto = new Photo({ src: "test.jpg", title:"testing"});
somePhoto.changeSrc("magic.jpg"); // which triggers "change:src" and logs update
5. Пример валидации
var Photo = Backbone.Model.extend({
validate: function(attribs){
if(attribs.src === undefined){
return "Remember to set a source for your image!";
}
},
initialize: function(){
console.log('this model has been initialized');
this.on("error", function(model, error){
console.log(error);
});
}
});
var myPhoto = new Photo();
myPhoto.set({ title: "On the beach" });
//logs Remember to set a source for your image!
6. Коллекции
• Позаимствованы из http://underscorejs.org/
– Унаследовали все методы
• Множество моделей, для которого реализованы:
– Фильтрация
– Сортировка
– Агрегация
• Реализуются посредством наследования стандартного класса
Backbone.Collection
• Базовый класс также реализует полезные методы (get, set,
length, push, pop, sort, create, fetch, pluck, where, ...)
• Позволяют централизовано работать с несколькими моделями
• Можно написать свой comparator
7. Пример коллекции
var PhotoCollection = Backbone.Collection.extend({
model: Photo
});
var a = new Photo({ title: 'my vacation'}),
b = new Photo({ title: 'my holiday'}),
c = new Photo({ title: 'my weekend'});
var photoCollection = new PhotoCollection([a,b]);
photoCollection.add(c);
photoCollection.remove([a,b]);
photoCollection.remove(c);
8. Пример коллекции
var PhotoCollection = new Backbone.Collection();
PhotoCollection.on("add", function(photo) {
console.log("I liked " + photo.get("title") + ' it's this one, right? ' + photo.get("src"));
});
PhotoCollection.add([
{title: "My trip to Bali", src: "bali‑trip.jpg"},
{title: "The flight home", src: "long‑flight‑oofta.jpg"},
{title: "Uploading pix", src: "too‑many‑pics.jpg"}
]);
var sortedByAlphabet = PhotoCollection.sortBy(function (photo) {
return photo.get("title").toLowerCase();
});
9. Представления
• Главная идея ‑ собрать интерфейс из
представлений, связанных с моделью
• Реиспользуемый элемент
пользовательского интерфейса
• Не содержит вёрстку документа
• Часто ассоциирован с моделью
• Создается посредством наследования
базового класса Backbone.View
10. Пример представления
var PhotoSearch = Backbone.View.extend({
el: $('#results'),
render: function( event ){
var compiled_template = _.template( $("#results‑template").html() );
this.$el.html( compiled_template(this.model.toJSON()) );
return this; //recommended as this enables calls to be chained.
},
events: {
"submit #searchForm": "search",
"click .reset": "reset",
"click .advanced": "switchContext"
},
search: function( event ){
//executed when a form '#searchForm' has been submitted
},
reset: function( event ){
//executed when an element with class "reset" has been clicked.
},
switchContext: function( event ){
//executed when an element with class "advanced" has been clicked.
}
});
11. Пример представления
• el ‑ это DOM‑элемент представления
tagName: 'p', // required, but defaults to 'div' if not set
className: 'container', // optional, you can assign multiple classes to this property like so 'container
homepage'
id: 'header', // optional
• Код выше создаст следующий DOMElement (но не добавит его в
дерево):
<p id="header" class="container"></p>
• Фунция render() определяет отображение представления на странице
• Исходные данные обычно задаются в JSON‑формате
• Для её реализации чаще всего используется сторонний
js‑шаблонизатор (например:
http://documentcloud.github.com/underscore/#template)
– Сюда то и уходит весь быдлокод ;)
13. Маршрутизация (Router)
• До версии 0.5 назывался Controller ;)
• Мэпит ссылки (URL) на функции в js
– Адресация в веб‑приложении
– Работа с историей в браузере
• на низком уровне: hashchange или HTML5
pushState
• После того как создали все роутеры нужно
скомандовать startBackbone.history.start, чтобы
история начала вестись
16. Персистентность
• Реализуется посредством функции Backbone.sync
– Она вызывается при каждой попытке прочитать/записать данные для
модели с сервера (fetch/save ...)
• url запроса определяется свойством model.url() или model.urlRoot()
– По умолчанию использует jQuery.ajax
– Может быть переопределена, например чтобы использовать WebSockets
– По умолчанию преобразует команды в следующие REST‑запросы:
– create → POST /collection
read → GET /collection[/id]
update → PUT /collection/id
delete → DELETE /collection/id
Пример обработчика на RoR:
def update
account = Account.find params[:id]
account.update_attributes params
render :json => account
end
17. Где почитать?
• Официальная документация (http://backbonejs.org/)
– Не хочешь учить англ? http://backbonejs.ru/
• Developing Backbone.js Applications
(http://addyosmani.github.com/backbone‑fundamentals/)
– Основы
– Примеры (готовый TODO‑лист)
– Тестирование
– Модульность
– Расширения
• Для чайников: http://habrahabr.ru/post/127049/
• Презентация про альтернативу:
http://prezi.com/plv0byja9ubh/mvvm‑knockoutjs/
18. Альтернативы
• Knockout (http://knockoutjs.com/)
• Ember.js (http://emberjs.com/)
• AngularJS (http://angularjs.org/)
• SpineJS (http://spinejs.com/docs/index)
– Очень любопытный аналог
– Написан на coffee‑script
(http://coffeescript.org/)