Модель MVC, хорошо зарекомендовала себя в разработке WEB приложений на стороне сервера. Желание использовать аналогичную архитектуру и на стороне браузера заставляет искать решение для Javascript.
Блуждая по интернету в поисках информации, я неизменно натыкался на упоминания о Backbone. И вот, воодушевившись статьей Написание сложных интерфейсов с Backbone.js, я решил использовать именно эту библиотеку. Как оказалось, документация и пример «TODO» достаточно сложны для быстрого понимания что это и с чем его едят. Поэтому, отбросив все что можно, я написал вот такую маленькую бесполезность, которая, надеюсь, поможет понять, почему Backbone — это круто и просто.
В документации к Backbone рекомендуется начальный список объектов загружать заранее. Так мы и поступим.
Блуждая по интернету в поисках информации, я неизменно натыкался на упоминания о Backbone. И вот, воодушевившись статьей Написание сложных интерфейсов с Backbone.js, я решил использовать именно эту библиотеку. Как оказалось, документация и пример «TODO» достаточно сложны для быстрого понимания что это и с чем его едят. Поэтому, отбросив все что можно, я написал вот такую маленькую бесполезность, которая, надеюсь, поможет понять, почему Backbone — это круто и просто.
В документации к Backbone рекомендуется начальный список объектов загружать заранее. Так мы и поступим.
// Предзагруженные элементы
var TC = [
{"id":"1", "name":"TC-1"},
{"id":"2", "name":"TC-2"}
]
* This source code was highlighted with Source Code Highlighter.
Главной частью приложения является модель. В данном примере она не делает ничего.
// Модель элемента.
var TCModel = Backbone.Model.extend({
initialize: function(){
// Просто отладочный вывод в консоль
console.log('TCModel', this.get('name'));
}
});
* This source code was highlighted with Source Code Highlighter.
В коллекции, как и следовало ожидать, хранятся модели или, точнее, экземпляры модели.
// Коллекция
var TCColl = Backbone.Collection.extend({
// Ссылка на модель
model: TCModel,
initialize: function(){
// Привязываем добавление элемента в коллекцию на событие 'add'
this.bind('add', this.addTC);
// В Underscore есть функция each, ей и пользуемся для перебора всех
// моделей в коллекции
_.each(this.models, this.addTC)
},
// Собственно, функция добавления элементов
// В аргументе ей передается модель
addTC: function(tc){
// Создаем вид для этой модели
var viewTC = new TCView({model:tc});
// И отрисовываем
viewTC.render();
}
});
* This source code was highlighted with Source Code Highlighter.
Мне не хотелось разрывать код на части, поэтому я оформил статью в виде комментариев.
// Вид одного элемента
var TCView = Backbone.View.extend({
// Элемент списка - это 'li', кто ни будь удивился?
tagName: "li",
initialize: function() {
// Отладочный вывод в консоль
console.log('init', this.model.attributes.name);
// Опять же, в Underscore есть функция bindAll
// Она позволяет "застолбить" за неким объектом
// некие функции. То есть при вызове метода "render"
// этого объекта this всегда будет этим объектом
_.bindAll(this, "render");
// Как только поменяется модель, тут то мы вид и перерисуем!
this.model.bind('change', this.render);
// В данном примере все будет работать и без этой строчки,
// но бывает полезно, когда модель знает о виде.
this.model.view = this;
// Так сказать, в нарушении популярного шаблона с каскадированием видов,
// я решил отображать вид прямо при инициализации.
// Попробуйте перенести эту строчку в render, получается забавный, но вполне объяснимый эффект
$('#sidebar').append(this.el);
},
render: function(){
// Как водится - отладка для порядка
console.log('render', this.model.attributes.name);
// Для сущей простоты обойдемся без шаблонов, выводя имя модели
this.el.innerHTML = this.model.get('name');
// И красисм это имя в цвет модели
$(this.el).css('color',this.model.get('color'));
// На всякий случай.
return this;
},
// Самое приятное в Backbone
events: {
// Просто событие : просто реакция
"click" : "paint"
},
// Вот оно самое, ради чего вся канитель
paint : function(){
// Отладка в консоль
console.log('paint',this);
// Обратите внимание! Мы меняем не цвет элемента в DOM,
// а цвет модели! Тоесть, изменить атрибут 'color' модели можно
// откуда угодно, не заморачиваясь поиском этого элемента в DOM
this.model.set({'color': '#'+Math.floor(Math.random()*16777215).toString(16)});
}
});
* This source code was highlighted with Source Code Highlighter.
Главный объект, то бишь, приложение. В немногочисленных примерах, встречающихся в сети, рекомендуется для приложения создавать отдельный вид. Ради простоты я отказался от инкапсуляции всего хозяйства в другой вид и для приложения создал отдельный объект не наследуемый от Backbone. Единственная определённая функция создаёт коллекцию внутри приложения.
App = {
init: function(){
this.tc_coll = new TCColl(TC);
}
};
* This source code was highlighted with Source Code Highlighter.
И собственно сам документ
<!DOCTYPE html>
<html>
<head>
<script src="jquery-1.6.js"></script>
<script src="underscore-min.js"></script>
<script src="backbone-min.js"></script>
<script src="app.js"></script>
<script type="text/javascript">
$(document).ready(function () {
// Тут инициализация
App.init();
// А тут произвольная работа с приложением
// Например, добавление элемента в коллекцию
App.tc_coll.add({id:3, name:'TC-4'});
});
</script>
</head>
<body>
<ul id="sidebar"></ul>
</body>
</html>
* This source code was highlighted with Source Code Highlighter.
Теперь, кликая по элементам, можно наблюдать как случайно изменяется их цвет.
Надеюсь, кому ни будь станет немного понятнее, как построить своё приложение при помощи Backbone