Начинаем работать с Ember.js

http://www.andymatthews.net/read/2012/03/07/Getting-Started-With-EmberJS
  • Перевод


В наши дни сложные Javascript-приложения можно увидеть повсюду. Со временем они становятся все сложнее и уже неприемлемо просто писать цепочку callback-функций на jQuery. Javascript-программисты постепенно узнают то, что обычные разработчики знали уже несколько десятилетий. Организация и эффективность может сыграть важную роль при разработке. Таким образом, такие MVC-фреймворки на Javascript, как Backbone, Knockout и Ember появились для того, чтобы заполнить пустоту между начинающими, средними и опытными разработчиками. Они предлагают разные возможности и функционал, который подойдет разным людям, в зависимости от их потребностей.

Я считаю себе довольно хорошим разработчиком… далеко не лучшим, но я умею работать с существующими технологиями, которые применяю в своих разработках. Я следил за этими фреймворками и мне подошли Backbone и Ember. Я игрался с Backbone, даже купил видео-учебник по нему. Он хороший, но мне до сих пор трудно заставить себя мыслить как он. Я услышал об Ember всего несколько месяцев назад и он все набирает обороты. Он предлагает множество функций, которые мне нужны и я решил посмотреть, насколько он мне подходит. Ember предоставляет несколько ключевых фич, которые мне кажутся очень привлекательными, главной из которых является привязка данных. Вы просто создаете переменную, и, когда значение этой переменной изменяется, обновляется любая часть вашего приложения, которая следит за этой переменной. Это нашло бы свое применение, например, в чатах и т. д.

На данный момент главный недостаток Ember по сравнению с Backbone в том, что у последнего есть множество учебников, статей и готовых проектов на Github. В то время, как по Ember вы можете найти совсем немного материалов в сети, которые сразу показывают все его внутренности, но упускают самые основы. Так что моя цель – написать туториал, который поможет начать вам использовать Ember уже сейчас. Ну и кроме всего прочего я пишу эту статью, чтобы закрепить свои собственные знания.

Ember.js построен на архитектуре MVC (Model-View-Controller) и вы просто должны разделять свой код на 3 части:

  • M = Модель – похожа на массив. Здесь хранятся данные, которые будут использоваться вашим приложением.
  • V = Представление – это визуальная часть вашего приложения — формы, списки и т. д.
  • C = Контроллер – думайте о контроллере, как о регулировщике движения. Он управляет взаимодействием между другими частями приложения. Когда пользователь нажимает на кнопку, контроллер определяет, какое представление должно быть загружено, которое в свою очередь определяет, какую модель использовать для сохранения данных.


Ну что, начнем? Для начала скачайте Ember.js Starter Kit. Распакуйте его в директорию, у которой есть доступ с веб-браузера. Откройте index.html и js/app.js в вашем любимом текстовом редакторе. В app.js добавьте следующую строку:

Welcome = Ember.Application.create();


Поздравляю! Вы создали свое первое приложение на Ember! Откройте index.html в вашем браузере и придите в восторг от вашего нового сайта. Ой, постойте, там же ничего нет… что вы думаете по этом поводу? Ничего не появилось кроме заголовка и это прекрасно. Все что произошло – это то, что Ember создал приложение, которое вы будете использовать на протяжении всего урока. Некоторые разработчики предпочитают называть это пространством имен. Это просто означает, что все другие части вашего приложения будут начинаться с имени, которое вы выбрали. Это помогает избежать конфликта имен переменных и держит все в порядке.

Есть одна вещь, к которой большинство jQuery-разработчиков очень привыкли – старый добрый document.ready. Ember предлагает нечто подобное, принимая необязательный объект в метод create. Добавьте код, перезагрузите страницу и вы должны увидеть поздравление. Погладьте себя по голове… вы это заслужили!

Welcome = Ember.Application.create({
	ready: function(){
		alert('Вы сделали это!');
	}
});


Следующее, что нам нужно сделать – это добавить Модель. Каждое приложение на Ember может иметь множество моделей и каждая из них – это уникальный тип данных. В некоторых фреймворках модель представляется в виде класса. В общем, это просто структура, которая говорит нам, как работать с этим объектом. Давайте создадим модель для некоторых из моих любимых книг.

Welcome.Book = Ember.Object.extend({
	title: null,
	author: null,
	genre: null
});


Следующее, что нам нужно – это контроллер. Кстати, кроме управления приложением, контроллеры в Ember так же передают данные из модели в представление. Вот простой контроллер на Ember:

Welcome.booksController = Ember.ArrayController.create();


Несовсем похоже на создание контроллера, но здесь создается ArrayController, который содержит массив. Именно здесь будет сохраняться информация о наших книгах. Она там, вы просто не видите ее. Вы можете явно указать содержимое массива, или, например, заполнить его. Это осуществляется путем передачи необязательного объекта метод create:

Welcome.booksController = Ember.ArrayController.create({
	content: []
});


Теперь у нас есть модель и контроллер – осталось только написать представление. Помните, я говорил, что представление – визуальная часть вашего приложения? Значит это будет находится в файле index.html. Давайте сначала напишем наше представление, а потом обсудим его. Прямо под тег H1 добавьте следующее:
<script type="text/x-handlebars">
	{{#view Ember.Button target="Welcome.booksController" action="loadBooks"}}
		Load Books
	{{/view}}

	{{#collection contentBinding="Welcome.booksController" tagName="ul"}}
		<b>{{content.title}}</b> - {{content.author}}, <i>{{content.genre}}</i>
	{{/collection}}
</script>


Одна из замечательных особенностей Ember – это то, что он поставляется с встроенным шаблонизатором Handlebars. По сути шаблоны являются ключевой магией Ember. Обычно в шаблонах вы окружаете переменную какой-то строкой. В Handlebars это 2 фигурные скобки.

Ember начал свое существование как билиотека SproutCore, разработанная в Apple, как ядро для их онлайн-приложений, таких как Mobile Me. SproutCore также включал в себя набор виджетов, которых нет в Ember. Ember включает в себя только предоставления для элементов форм, потому что они могут быть очень динамичными. В случае нашего шаблона, или представления, мы используем кнопки Ember. Это позволяет ему сделать всю тяжелую работу за нас. Он принимает цель (в нашем случае – booksController) и дейстие. Поэтому, когда кто-то нажимает на кнопку, Ember будет работать с методом loadBooks объекта Welcome.booksController.

Вторая часть немного сложнее, но я уверен, что вы разберетесь. В Ember коллекция – это просто указатель на группу данных, в нашем случае это опять Welcome.booksController. В начале статьи я писал, что связанные данные – одна из причин, по которой Ember меня заинтересовал. И здесь мы можем увидеть всю его мощь. Content просто указывает на переменную content в booksController, в то время, как Binding является той самой волшебной пылью. Добавление Binding к концу большинства атрибутов говорит Ember о том, что вы хотите сделать двустороннее связывание. Вы изменяете значение на одной стороне, а другая будет обновляться. Наконец, коллекции позволяют установить базовый тег, в нашем случае это просто маркированный список (тег UL).

Кстати, символы # и / говорят Handlebars о том, что это только часть (блок) представления.

Внутри коллекции находится “мясо” наших шаблонов. Обратите внимание, как мы смешиваем HTML и теги внутри наших шаблонов. Удобно, не правда ли? Друга тонкость состоит в том, что Ember не нуждается в явном указании открывающих или закрывающих тегов для списка. Он добавит их автоматически, потому что знает, что мы используем маркированный список. Запустите приложение и вы увидите одинокую кнопку, которой нужны друзья. Нажатие кнопки делает ее несчастной, т. к. у нас еще нет метода loadBooks. Как насчет того, чтобы добавить его и загрузить немного данных?

Welcome.booksController = Ember.ArrayController.create({
	content: [],
	loadBooks: function(){
		var self = this;
		$.getJSON('data/books.json', function(data) {
			data.forEach(function(item){
				self.pushObject(Welcome.Book.create(item));
			});
		});
	}
});


Помните, мы говорили, что модели могут содержать произвольные методы? Все в Ember может содержать произвольный код, в том числе и ArrayController. Теперь, когда вы загрузите свою страницу и нажмете кнопку “Load Books” — будет вызван метод loadBooks, который загрузит некоторые из моих любимых книг. Вот и все для этого простого примера. Я надеюсь, что вам понравилось и вы дадите Ember шанс. Вы можете скачать исходный код примера на Github.

Подождите еще минутку. Если вы похожи на меня, то у вас остались вопросы. Много вопросов. Я написал эту статью потому, что были вопросы и у меня ушли часы на поиск ответов. На самом деле ответы на большинство вопросов, которые у меня были освещены в этой статье. Если у вас еще остались вопросы, то вы можете написать их здесь. Если я не знаю ответа, то я его найду и отвечу вам.

Советую вам прочитать мою вторую статью, в которой Ember освещен намного подробнее.
Поделиться публикацией

Похожие публикации

Комментарии 33
    0
    Только что прочитал доки на их сайте, захожу на хабр, а тут эта статья, отлично :)
      +11
      Специалисты, поясните пожалуйста — в чём преимущества/недостатки Ember.js перед Backbone.js. Спасибо.
        +1
        Тут подробно расписаны отличия (и не только между ember и backbone) – coding.smashingmagazine.com/2012/07/27/journey-through-the-javascript-mvc-jungle/
          +1
          Судя по статье, в Ember нет бОльшей части функционала Backbone. В Backbone хорошо реализованы модели, наследование, коллекции. Есть синхронизация модели с сервером из коробки. При этом они никак не завязаны на отображение. Это именно средства для описания предметной области — модели данных. С другой стороны отображения (Views) в Backbone многим кажутся громоздкими. Я думаю им стоило бы изобразительную часть сделать опциональной.

          Я использую сейчас связку: Backbone + Knockout через надстройку Knockback. При этом есть еще одна надстройка над Backbone — Backbone-Relational. Более того серверная часть на NodeJS, так что модель данных для сервера и клиента у меня описывают одни и тот же файлы. Для сервера модели дополнительно расширяются. A Backbone-Relational в автомате помогает поддерживать связи между моделями. Пока что все красиво, но и не без особенностей. Knockback используется на клиенте — он просто позволяет облегчить конвертирование моделей Backbone в ViewModels Knockouta.
            +1
            Как заявляют разработчки, ember стремится уменьшить кол-во «шаблонного кода», т.е. в нем сразу выбраны решения для типичных задач.
            Основное преимущество и видимо одновременно и недостаток — это байндинги данных к Handlebars шаблонам. Что позволяет очень удобно автоматически обновлять страницу при изменениях. А с другой стороны это же накладывает некоторые ограничения на генерируемый по умолчанию html и он немного «замусоревается» служебными тегами, которые нужны ember для поддержки этой автоматики.
            Ну и есть вопрос насколько гибко и быстро это будет работать в случае большого и/или сложного приложения. Хотя разработчики, вроде бы, обещают, что с этим все хорошо.

            Также хорошо выглядит возможнось создавать вложенные view (пример из документации):
            App.UserView = Ember.View.extend({
            	templateName: 'user',
            	// ...
            
            	infoView: Ember.View.extend({
            		templateName: 'info'
            		// ...
            	})
            });
            

            Это позволяет управлять довольно маленькими блоками страницы и повторно их использовать в других view.

            Не могу сказать, что у меня сильно большой опыт работы с backbone и ember, но поигравшись с ними в небольших проектах, мне ember кажется удобнее и производит хорошее впечатление.
              0
              Ember = Sproutcore -> у Sproutcore есть dataStore и это круто
              0
              Если вторая статья ваша, то было бы хорошо, либо более полную на Русском, либо перевод той статьи, для того чтобы было все в одном месте.
                0
                Очень любопытны биндинги, которые есть в Ember.js. Это точно MVC фреймворк?

                И да KnockoutJS это чистой воды MVVM, а не MVC.
                  0
                  Все эти JS Frameworks черезчур запутанные и каждый пытается навязать свою идеологию.
                  Стоит ли все так усложнять на стороне клиента?
                  Не проще ли писать на JQuery более очевидные конструкции?
                  А то получается и на стороне сервера у нас MVC и на клиенте MVC. Количество кода вырастает в разы!
                  Где преимущество? В чем фишка? Я так и не увидел.
                    0
                    Ты и тут можешь использовать жиквери.
                    Если пишешь приложение, в котором есть крудо-подобные операции (а они почти всегда есть), то очень сложно следить за data consistency в нескольких местах одновременно (появляется много говнокода, жестких зависимостей в коде), здесь помогает эмбер, и еще он помогает сериализовать данные из хтмл в js-объекты (в случае использования биндингов на инпуты), ну и еще много с чем помогает
                      0
                      Вы не натыкались в сети на open-source приложение приближенное к реальности? Или хороший пример?
                        0
                        опен-сорс приближенные к реальности не видел (только туду, но это так себе конечно).
                        из комментов в блоге эмбер знаю, что этот сайт использует его www.uniiverse.com/, но я не смотрел исходники (это не реклама:))
                      –5
                      +146!

                      В нативном JS есть всё что нужно для организации кода\приложения и т.п. Есть jQuery для работы с HTML-элементами. Есть Node.js для сервера.
                      Есть тысячи плагинов для практических целей — красивый диалог, коннектор к базе данных, работа с Canvas или обёртка для ImageMagick, да что угодно есть!

                      Объясните мне хоть кто-нибудь, ЗАЧЕМ вот эти монструозные фреймворки, каждый из которых, как написали выше, продвигает свою «правильную, гениальную, всё-одной-строчкой» идею?
                        +2
                        jQuery код в более-менее сложном приложении скатиться в лапшу и все эти «тысячи плагинов» не помогут решить вопрос организации кода и создания какой-либо архитектуры. А сейчас все меньше сайтов и все больше веб-приложений со сложной логикой. И все больше кода так скажем уходит с сервера на клиент, что заставляет искать соответствующие подходы.

                        Да, каждый фреймворк предоставляет свой «путь». Разработчик выбирает, что ему ближе, все в общем то как и с сервер сайд фреймворками.
                          0
                          С «организацией кода» и «созданием какой-нибудь архитектуры» никакой фреймворк не поможет, если разработчик не понимает, как надо организовать код. А если понимает — то крупный фреймворк (в большинстве случаев) будет избыточен.
                            0
                            Это просто два разных подхода. И каждый имеет право на существование. Кто-то использует «низкоуровневые» библиотеки и строит фундамент самостоятельно, кто-то испольует фреймворки, которые предоставляют базис. И так не только в мире JS. Дескутировать на тему, что лучше — можно вечно.
                              0
                              Чуть-чуть поясню свою позицию (если кому-то интересно): я не против фреймворков, а против избыточности. Допустим, jQuery — достаточно крупный функциональный фреймворк, но в любом крупном проекте он будет задействован по-полной — и работа с HTML-структурой, и AJAX, и CSS-анимации всякие и т.п.
                              А в фреймворке из статьи — например, не проще ли выкинуть чепуху вида
                              Welcome.Book = Ember.Object.extend({
                              title: null,
                              author: null,
                              genre: null
                              });

                              и просто создать банальный нативный конструктор
                              var Book = function(){
                              // всяко-разно
                              };
                              Book.prototype. //дальше уж что хотите
                                0
                                Не забывайте, что jquery — это не фреймворк, а библиотека. И задачи у ember и jquery разные. Будет неправильно вот так просто сравнивать их.
                        0
                        > Не проще ли писать на JQuery более очевидные конструкции?
                        На клиенте сейчас растет количестко кода и в больших приложениях jQuery просто не достаточно. jQuery это DOM обертка, которая никак не поможет вам организовать кодовую базу.

                        > А то получается и на стороне сервера у нас MVC и на клиенте MVC. Количество кода вырастает в разы!
                        Если честно то сейчас в некоторых случаях MVC(и модификации) более необходим оказывается на клиенте чем на сервере. Да и MVC архитектура пришла с десктопных аппликаций, а нынешний веб в ряде случаев все больше и больше напоминает десктоп.
                          –3
                          ок, сам по себе подход мне нравится, но как насчет безопасности? Во первых это позволяет пользователям изучить ваш код (как бэ интеллектуальная собственность и всё такое), а во вторых вносить правки в этот код!
                          Понятно, что по хорошему все проверки на валидность поступающих данных нужно дублировать на бэкэнде. Но всёже, как насчет того, что любой может посмотреть и изучить ваш код?
                            0
                            А в чем проблема изучения аналогичного кода без применения MVC?
                              0
                              Я про перенос логики на клиента в целом, а не конкретно об MVC
                          0
                          на стороне серваре не MVC, а REST API. Ember.js это фреймворк для одностраничных приложение прежде всего.
                          0
                          Из статьи заметил, что работа с моделью находится в зародишевой стадии. Вытаскивать вручную данные и заполнять коллекцию не очень удобно. Тот же backbone имеет надстройки для синхронизации данных, что делает коммуникацию с сервером более прозрачной.

                          Те вместо
                          $.getJSON('data/books.json', function(data) { data.forEach(function(item){ self.pushObject(Welcome.Book.create(item)); }); });
                          было бы куда приятнее сделать
                          Welcome.Book.load()
                            0
                            блин, форматирование пропало :(
                              0
                              Там есть свой DataStore https://github.com/emberjs/data, который как раз и позволяет делать приблизительно то, что Вы хотите
                              var people = App.store.findAll(App.Person);
                              
                              +10
                              Я не смог спокойно читать эту статью, смысл все время ускользал от меня!
                                0
                                В свое время приглядывался к этому фреймворку, параллельно использовал backbone. Теперь активно использую angularjs. Он для меня более прозрачный и понятный, плюс у него есть такая очень крутая киллер фитча под названием AngularJS Batarang
                                  0
                                  Вроде выглядит не плохо, да еще и от гугла, вопрос только — как жить с тем, что иде будут ругаться на невалидные атрибуты
                                    +1
                                    Я предпочитаю использовать не IDE с javascript. Точнее, я пишу весь клиентский код на CoffeeScript с использованием Sublime Text 2. Однако знаю что плагин для angularjs в планах для Intellij Idea.
                                      +1
                                      Ох, извиняюсь, невнимательно прочел ваш комментарий. Angular поддерживает все свои аттрибуты в формате data-название-аттрибута. Любая IDE, понимающая HTML5 не будет ругаться.
                                      0
                                      Хорошая библиотечка, только я слабо понимаю, как ее совместить со статичным контентом, на случай выключенного жс у пользователя.
                                        0
                                        AngularJS предназначен для создания навороченых одностраничных приложений (аля гмайл). Если так сильно требуется охватить жалкий процент пользователей с отключенными скриптами в продукте такого типа, то почему не сделать лайт версию (как тот же гмайл).

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое