Сегодня я напишу небольшое приложение на Backbone, например канонический телефонный справочник. И по шагам, начиная с азов покажу как всё работает. Поехали.
Что такое Backbone? Это и фреймворк и способ организации вашего js-приложения. Он проще чем Ember, и на мой взгляд логичнее чем Angular. На его изучение уйдёт никак не больше месяца, а освоив этот инструмент вы вполне сможете претендовать на начинающие позиции во frontend разработке.
Основа основ – модели. Минимальной единицей приложения на Backbone являются модель.:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
var ContactModel = Backbone.Model.extend({ default : { name : "", photo : "", id : "", phone : "" }, validate : function(attributes){ if (!attributes.name) return "Пожалуйста, укажите имя контакта" if (!attributes.id) return "Пожалуйста, укажите ID контакта" }, initialize : function(object){ console.log('Hello. My ID is ' + object.id) } }) var mytya = new ContactModel({ name : "Митя", id : 1, phone : "+7 (999) 000-00-00" }); var oksana = new ContactModel({ name : "Оксана", id : 2, phone : "+7 (999) 111-11-11" }); |
Создана первая модель которая состоит из нескольких полей и пары методов. Пока всё довольно просто, модель – каркас наших данных. Обратите внимание на метод initialize, им обладает любой “каркас” в Backbone, и именно он вызывается перед созданием объекта по этому каркасу. Другими важными составляющими модели являются события и валидация, но о них поговорим позже.
Чтож, у нас есть каркас, есть данные по этому каркасу – mytya и oksana, всё готово чтобы показать их на странице.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var ContactView = Backbone.View.extend({ initialize : function(){ this.render(); }, template : _.template("<h1><%= title %></h1><img src='<%= img %>' />"), render : function () { this.$el.append(this.template(this.model.toJSON())) return this; } // Без использования шаблонов от underscore, наш метод render мог бы выглядеть так: // render : function(){ // this.$el.append("<h1><a href='" + this.model.get("id") + "'></a>" + this.model.get('title') + "</h1><img src=" + this.model.get('img') + "/>") // return this // } }) |
Важно понять, основа всего представления, главный элемент – el или $el. el – это будущий элемент DOM в который вы вставляете все свои данные (this.$el.append).
1 2 |
$('body').append(new ContactView({model: mytya}).el); $('body').append(new ContactView({model: oksana}).el); |
Ура, первое, самое простое приложение готово. И вы, надеюсь, разобрались что такое модель и представление.
На очереди “Коллекции”, давайте создадим новую коллекцию и отметим что в неё могут входить определённые модели:
1 2 3 |
var ContactCollection = Backbone.Collection.extend({ model : ContactModel }) |
Для того чтобы добавить наши контакты в коллекцию ContactCollection можно использовать встроенный в коллекции метод add, или просто передать массив объектов.
1 2 3 4 5 6 |
var contacts = new ContactCollection([mytya, oksana]) // что равноценно var contacts = new ContactCollection() contacts.add(mytya, oksana) |
У нас есть View для модели, но нет для списка. Давайте уже создадим, тем более там мы будем использовать уже созданный ContactView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var ContactCollectionView = Backbone.View.extend({ initialize : function(){ this.render(); }, render : function(){ this.collection.forEach(function(framework){ this.$el.append(new ContactView({model : framework}).el) }, this) // Здесь последний параметр - контекст, иначе this для безымянной функции - глобальный объект. return this } }) // Вызвать список на страницу: $('body').append(new ContactCollectionView({collection : contacts}).el); |
На этом первая часть завершена, дальше я расскажу о роутерах и мы создадим простой справочник контактов с хранением контактов в localStorage и поиском по ним.
P.S. Завершённый код этой статьи:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script type="text/javascript" src="./node_modules/underscore/underscore-min.js"></script> <script type="text/javascript" src="./node_modules/jquery/dist/jquery.min.js"></script> <script type="text/javascript" src="./node_modules/backbone/backbone-min.js"></script> </head> <body> <div id="posts"></div> <!--<script type="text/javascript" src="./app.js" ></script>--> <script type="text/javascript"> var ContactModel = Backbone.Model.extend({ default : { name : "", photo : "http://icons.iconarchive.com/icons/custom-icon-design/pretty-office-2/256/man-icon.png", id : "", phone : "" }, validate : function(attributes){ if (!attributes.name) return "Пожалуйст, укажите имя контакта" if (!attributes.id) return "Пожалуйст, укажите ID контакта" }, initialize : function(object){ console.log('Hello. My ID is ' + object.id) } }) var mytya = new ContactModel({ name : "Митя", id : 1, phone : "+7 (999) 000-00-00", photo : "http://icons.iconarchive.com/icons/custom-icon-design/pretty-office-2/256/man-icon.png" }); var oksana = new ContactModel({ name : "Оксана", id : 2, phone : "+7 (999) 111-11-11", photo : "http://icons.iconarchive.com/icons/custom-icon-design/pretty-office-2/256/man-icon.png" }); var ContactView = Backbone.View.extend({ initialize : function(){ this.render(); }, template : _.template("<img src='<%= photo %>' align='left' width='40px' /> <h1><%= name %></h1>"), render : function () { this.$el.append(this.template(this.model.toJSON())) return this; } // Без использования шаблонов от underscore, наш метод render мог бы выглядеть так: // render : function(){ // this.$el.append("<h1><a href='" + this.model.get("id") + "'></a>" + this.model.get('title') + "</h1><img src=" + this.model.get('img') + "/>") // return this // } }) var ContactCollection = Backbone.Collection.extend({ model : ContactModel }) var contacts = new ContactCollection([mytya, oksana]) var ContactCollectionView = Backbone.View.extend({ initialize : function(){ this.render(); }, render : function(){ this.collection.forEach(function(framework){ this.$el.append(new ContactView({model : framework}).el) }, this) // Здесь последний параметр - контекст, иначе this для безымянной функции - глобальный объект. return this } }) $('body').append(new ContactCollectionView({collection : contacts}).el); </script> </body> </html> |
Ссылки по теме:
– http://habrahabr.ru/company/piter/blog/212023/
– http://beletsky.net/blog/categories/backbone-dot-js/
Здравствуйте, подключив ваш код получил такую ошибку в консоли
backbone.js:1101 Uncaught TypeError: Backbone.$ is not a function
не могу разобраться с ее решением. Есть ли у вас мысли по этому поводу?
Нашел ответ здесь https://stackoverflow.com/questions/19528559/is-not-a-function-backbone-jquery-and-browserify
Backbone ищет jquery в глобальной переменной (которая определяется путем ее захвата), и вполне вероятно, что браузер запускает скрипт не в глобальном контексте