Информационный портал по безопасности. Создание модульных компонент. Жизненный цикл компонента

У нас был пример с формой, которая отображала результат мгновенно, как только пользователь введет что-нибудь в поле ввода.

Так вот на официальном сайте Ember.JS есть похожий пример.

XHTML

Name: {{input type="text" value=name placeholder="Enter your name"}} My name is {{name}} and I want to learn Ember!

Name:

{{input type="text" value=name placeholder="Enter your name"}}

My name is {{name}} and I want to learn Ember!

Ember, как и Angular имеет двустороннее связывание. Но в отличие от последнего он не использует атрибуты html для связывания. Вместо этого используется шаблонизатор Handlebars и магия маршрутов (routes).

Говорят, что Ember — штука сложная, с высоким порогом вхождения. Похоже, что это на самом деле так. Прежде чем сделать мало мальски сносное приложения необходимо понять как работает Ember и какой объект в каком месте работает. Этому я посвящу следующую статью, а сейчас еще немного в общем.

Конечно у Ember.JS есть то, за что одностраничное приложение называется одностраничным — роутинг. При, практически, любых действиях пользователя у нас меняется URI в строке URL браузера. Этот адрес мы можем использовать для передачи кому-нибудь.

Так же как и у Ангуляра, у этого фреймворка есть средства тестирования, которые позволяют тестировать как отдельные компоненты приложения (модульное тестирование), так и группами (интеграционные тесты).

Есть свой инструмент отладки — Ember Inspector . Это плагин для FireFox и Chrome, который позволяет видеть, что происходит внутри приложения. Например, видеть какие шаблоны загружаются при определенном URI.

Встроенных инструментов для построения и валидации форм похоже нет, но есть надстройка Ember Forms , которая позволяет это делать.

Как видно Ember и Angular во многом похожи, но все же они разные. Сломано не мало копий в темах о том, что же лучше одно или другое. По сообщениях в этих спорах видно, что Ember более многословен и потребует больше кода при написании приложения. Angular дает больше свободы в том, как именно реализовывать задачу. Однако создается впечатление, что код Ember легче будет поддерживать, так как он более структурирован. Хотя кажется мы сейчас начнем скатываться в холивар. на Хабре со сравнением Ember и Angular. Если вдруг потонет в пучинах сети, то можно почитать копию .

Если бегло говорить об Ember, то пожалуй это всё. Конечно же теперь интересно сделать небольшое, но реальное приложение на этом фреймворке. В этом нам поможет .

Ember.js - зрелый фронтенд фреймворк, получивший много внимания в последнее время. Это статья познакомит вас с основными концепциями фреймворка на примере создания простого приложения и покажет, что с его помощью можно сделать.

Мы собираемся написать приложение Dice Roller, позволяющее кинуть кости и посмотреть историю всех совершенных бросков. Полностью работающие приложение можно увидеть на GitHub .

Ember.js вобрал в себя множество современных JavaScript концепций и технологий. Вот их неполный список:

  • Транспайлер Babel для полноценной поддержки ES2015 синтаксиса.
  • Поддержка юнит, интеграционного и приемочного тестирований с помощью Testem и QUnit .
  • Brocolli.js для сборки ассетов.
  • Поддержка live-reload для сокращения отклика во время разработки.
  • Шаблонизация с использованием Handlebars .
  • Навигация в любую часть приложения благодаря системе роутинга.
  • Полная поддержка JSON API , но при этом присутствует возможность использовать любой API, который вам необходим.

Для работы с Ember.js предполагается, что у вас установлены свежие версии Node.js и npm. Если нет, то их можно скачать и установить с сайта Node.js .

Также стоит упомянуть, что Ember - исключительно фронтенд фреймворк. Есть множество способов взаимодействия с бэкендом на ваш выбор, но сам бэкенд никак не управляется Ember.

Знакомство с ember-cli

Немало возможностей Ember.js связано с его интерфейсом командной строки или CLI . Этот инструмент, известный как ember-cli, управляет большой частью процесса разработки: от создания приложения и добавления различного функционала и до запуска тестов и деплоя на продакшен.

Практически всё во время разработки Ember.js приложения будет в какой-то степени связано с этим инструментом, поэтому важно понимать как им пользоваться. Мы будем использовать его при создании нашего приложения.

Первым делом нужно убедиться, что ember-cli установлен и актуален. Устанавливаем его c помощью npm:

$ npm install -g ember-cli

и проверяем успешность установки:

$ ember --version
ember-cli: 2.15.0-beta.1
node: 8.2.1
os: darwin x64

Создание вашего первого Ember.js приложения

С установленным ember-cli мы готовы приступить к созданию нашего приложения. В первый раз мы будем использовать ember-cli для того, чтобы создать всю структуру приложения и сделать первоначальные настройки.

Наше приложение создалось и готово. У нас даже настроился Git, как система контроля версий.

Примечание: Вы можете отключить интеграцию с Git, а также использовать Yarn вместо npm. Используйте команду ember new --help для более подробной информации.

Запуск сервера Ember.js приложения для целей разработки делается также с помощью ember-cli:

Всё готово. Приложение запущено по адресу http://localhost:4200 и выглядит следующим образом:

Добавление подобного стороннего контента может быть осуществленно несколькими способами:

  • Указанием ссылки на внешний CDN сервис
  • С помощью пакетных менеджеров вроде npm или Bower
  • Подключив напрямую в приложение из папки vendor/
  • Использовать Ember Addon , если такой имеется

К сожалению, аддон для Materialize пока что не совместим с последней версией Ember, поэтому мы просто добавим ссылку на него. Чтобы сделать это, мы обновим app/index.html файл, являющийся корневой страницей, в которую будет отрендерено наше приложение. Мы хотим добавить ссылки на CDN для jQuery, Google Icon Font и Materialize.

Теперь мы можем обновить нашу главную страницу, добавив разметки. Для этого отредактируем файл app/templates/application.hbs:

В браузере это должно выглядеть так:

Так, что же такое outlet тэг? Ember работает на основе роутов, где каждый роут является ребенком другого роута. Самый верхний роут в этой иерархии обрабатывается Ember автоматически и рендерит шаблон app/templates/application.hbs .

Тэг outlet определяет, где Ember отрендерит следующий роут в текущей иерархии. Таким образом роут первого уровня будет отрендерен в добавленный нами тэг в application.hbs , а роут второго уровня будет отрендерен в такой же тэг в темплейте роута первого уровня. И так далее.

Создание нового роута

В Ember.js приложении каждая посещаемая страница доступна с помощью роута . Существует прямая связь между адресной строкой (URL) в браузере и роутом в приложении.

Проще показать это на примере. Давайте добавим новый роут в наше приложение, позволяющий пользователю бросать кости. И вновь это делается с помощью ember-cli:

Что создалось с помощью этой команды?

  • Обработчик для роута -  app/routes/roll.js
  • Шаблон для роута -  app/templates/roll.hbs
  • Тест для роута tests/unit/routes/roll-test.js
  • Новый роут добавился в файл конфигурации роутера -  app/router.js

Давайте посмотрим на это в действии. Для начала мы хотим создать довольно простую страницу, позволяющую нам получить число после броска костей. Для этого обновим файл app/templates/roll.hbs:

Результат будет доступен в браузере по адресу http://localhost:4200/roll :

Теперь нам нужна возможность попадать на эту страницу с главной страницы. Ember позволяет сделать это очень просто с помощью хелпера link-to , который принимает первым аргументом имя роута и рендерится в разметку, позволяющую нашему пользователю попасть на нужный роут.

В нашем случае нужно обновить файл app/templates/application.hbs , чтобы он содержал следующее:

Создание модульных компонент

Если на данном этапе вы попробовали протестировать наше приложение, то могли заметить одну проблему. Переход по ссылке в роут roll работает корректно, но метки элементов форм не выстраиваются правильно. Это происходит потому что Materialize нужно использовать JavaScript, чтобы поставить метки на свои места, после того как они будут отрендерены. Но динамический роутинг предполагает, что страница не будет перезагружена. Таким образом, у нас пока что нет места, где можно инициализировать этот JavaScript код.

На помощь приходят компоненты. Компоненты - это частички интерфейса пользователя, имеющие свой жизненный цикл, с которым мы можем взаимодействовать и в который мы можем встроить необходимый нам JavaScript код. Также они используются для создания переиспользуемых элементов интерфейса, но к этому мы ещё вернёмся.

Пока что мы собираемся создать компонент, представляющий собой форму для броска костей. Как обычно, создание компонента тоже можно осуществить с помощью ember-cli:

$ ember generate component roll-dice
installing component
create app/components/roll-dice.js
create app/templates/components/roll-dice.hbs
installing component-test
create tests/integration/components/roll-dice-test.js

Мы получили:

  • app/components/roll-dice.js  - код, управляющий компонентом
  • app/templates/components/roll-dice.hbs  - шаблон компонента, где мы определим, как он выглядит
  • tests/integration/components/roll-dice-test.js  - тест, чтобы удостовериться, что компонент работает правильно

Мы перенесём всю разметку из роута roll в компонент, что не повлияет на работу приложения в целом, но позволит нам использовать всю силу компонент.

Обновим шаблон компонента app/templates/components/roll-dice.hbs:

А также шаблон роута app/templates/roll.hbs:

Тэг roll-dice в шаблоне говорит Ember, где отрендерить наш компонент.

Жизненный цикл компонента

Компоненты в Ember имеют заданный жизненный цикл, которому они следуют, с множеством хуков, вызываемых на различных стадиях. Мы используем хук didRender , который будет вызван после того, как компонент будет отрендерен (в первый раз или в любые последующие), чтобы попросить Materialize обновить метки элементов форм.

Сделать это можно, обновив код компонента app/components/roll-dice.js таким образом:

Теперь при любом заходе в роут roll нужный нам код отработает и Materialize исправит отображение меток.

Связывание данных

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

Каждая частичка данных, с которой мы хотим взаимодействовать, имеет свое собственное поле в классе компонента. Когда мы хотим показать поля ввода, мы используем специальные хелперы в шаблоне компонента, связывающие поля ввода с переменными/полями в классе компонента. Таким образом, мы взаимодействует с полями ввода напрямую, не беспокоясь о работе с DOM.

В нашем случае у нас есть три поля ввода, поэтому нам нужно добавить три строчки внутри класса компонента в файле app/components/roll-dice.js:

Затем мы обновим наш шаблон, заменив HTML разметку полей ввода на специальные хелперы.

Обратите внимание, что атрибут value имеет слегка странный синтаксис. Подобный синтаксис может быть использован с любым атрибутом хелпера, не только с value . Вообще существует три способа передачи значения в атрибут:

  • Как строку в кавычках (значением будет эта строка
  • Как строку без кавычек (в этом случае значение будет взято из одноименного поля в классе компоненты, но компонента никогда не обновится)
  • С использованием (mut ) (значение также возьмется из одноименного поля в классе компонента, но компонент будет изменяться, когда значение изменится в браузере)

Всё вышеизложенное означает, что теперь мы можем обращаться к добавленным в компонент полям как к значениям полей ввода, а всё остальное сделает Ember.

Экшены компонент

Следующим шагом мы хотим добавить компоненту интерактивность. Например, хорошо бы обрабатывать нажатие кнопки «Бросить кость». Для этого в Ember есть экшены. Это методы, описанные в классе компонента, которые могут быть подключены в шаблон компонента. Обычно методы описывают в специальном объекте компонента actions .

Добавим экшен в наш компонент app/components/roll-dice.js:

Мы возвращаем false , чтобы предотвратить всплытие события . Это довольно стандартная процедура в веб-приложениях и в данном случае предотвращает отправку формы и перезагрузку страницы.

Вы можете заметить, что мы ссылаемся на поля, которые мы ранее объявили в классе, чтобы иметь доступ к значениям полей ввода. Здесь нет никакого взаимодействия с DOM: мы оперируем только JavaScript переменными.

Осталось подключить наш экшен. В шаблоне нам нужно сказать тэгу формы, что ему нужно вызвать triggerRoll экшен, когда случится событие onsubmit . Это делается добавлением всего одного атрибута с использованием action хелпера. В шаблоне app/templates/components/roll-dice.hbs это выглядит так:

Заполнив поля формы и нажав на кнопку, мы увидим диалоговое окно с результатом нашего ввода.

Взаимодействие с сервером

Следующим шагом будет написание логики настоящего броска кости. Это требует взаимодействия с сервером, так как сервер ответственен за запоминание результата броска кости.

Мы хотим достичь следующего:

  • Пользователь определяет параметры для броска кости
  • Пользователь нажимает на кнопку «Бросить кость»
  • Приложение выполняет логику броска кости и отправляет результат и параметры совершенного броска на сервер
  • Сервер запоминает результат и сообщает клиенту об удачном сохранении
  • Браузер отображает результат броска

Звучит довольно просто. И конечно, с Ember, это действительно так.

Ember управляет этим, используя встроенную концепцию хранилища -  Store , наполненного моделями - Models . Хранилище  - единственный источник знаний о данных во всем приложении, а модель представляет часть этих данных в хранилище. Модели сами знают как сохранить себя на сервер, а хранилище знает как создавать и управлять моделями.

Передача управления от компонент в роуты

Очень важно сохранять инкапсуляцию во всем нашем приложении. Роуты (и контроллеры, о которых мы не будем говорить здесь) имеют доступ к хранилищу. Компоненты - нет.

Это потому что роуты отвечают за определенную бизнес-логику в приложении, в то время как компоненты представляют собой маленькие кусочки интерфейса. Чтобы всё работало как надо, компоненты способны посылать сигналы вверх по иерархии вложенности, когда происходит какое-либо событие. Это очень похоже на то, как хелперы в шаблоне компонента посылают сигналы в компонент, когда что-то произошло.

Для начала переместим логику показа диалогового окна из компонента в роут. Для этого нам нужно изменить некоторые части нашего кода.

В классе, ответственном за управление роутом app/routes/roll.js зарегистрируем экшен saveRoll , которым мы собираемся выполнить:

И перепишем логику экшена компонента. Теперь мы хотим вызвать другой экшен в нашем компоненте, передав параметры броска в его аргументы. Это делается с помощью метода sendAction , доступного в классе компонента.

  • Разработка веб-сайтов
  • В последнее время в вебе идет тенденция к «утончению» сервера и «утолщению» клиента. С каждым днем вакансий Full-stack разработчиков становится все больше, а чистого бэкенда все меньше. Последние 2 года я работаю разработчиком Ruby on Rails и в скором будущем без работы остаться не хотелось бы. Поэтому я начал рассматривать варианты изучения клиентского фреймворка.

    Вариантов было несколько:

    • Meteor
    • Angular
    • Ember
    Но остаться должен только один. Meteor предлагает интересную концепцию – общий код клиента и сервера, но он пока сыроват и мне не хотелось оставлять прекрасный язык Ruby. Поэтому Метеор отпал. Так как Ember был похож на Rails (магия, convention over configuration), то был выбран именно он. Помимо этого, очень симпатично выглядел шаблонизатор Handlebars по сравнению с директивами Angular.

    Выбор сделан. Вот тут и начались проблемы.

    Руководство написан очень неплохо, все делается хорошо, но вот когда начинаешь что-то делать сам, возникают постоянные вопросы. Основной проблемой у меня было то, что я не видел картину в целом, не понимал архитектуру. Статей на эту тему мало, а те что есть, рассказывают про самые базовые понятия, поэтому и появилась данная заметка.

    Ember называют MVC фреймворком, поэтому я ожидал увидеть что-то похожее на Ruby on Rails и классический MVC. Но не тут то было! Помимо модели, представления и контроллера (которые делают совсем другие вещи чем на сервере), здесь было много разных вещей: компоненты, маршруты, адаптеры, сериализаторы, шаблоны, хранилище.

    Жизненный путь запроса


    Рассмотрим схему более детально.Точка входа Приложение у нас одностраничное, так что точка входа у нас одна - index.html . Все переходы будут делаться с помощью якоря или history api. Все пути будут рабочими, то есть вы можете легко добавить нужную страницу в закладки и контент будет доступен по ней.Маршрутизатор Первым делом у нас работает Router. Именно он выбирает что делать дальше в зависимости от адреса и передает управление указанному в нем маршруту. Маршрут Route обрабатывает входящие данные, например параметры url, и обращается к модели или моделям. Он является связующим звеном между данными(Model) и их обработчиком (Controller).Модель Модели – это наши сущности, например в блоге – пост, пользователь, комментарий. Здесь уже используется не чистый Ember, а его дополнение – Data.
    Для того чтобы получить указанные объекты есть 2 варианта:
  • Получить их с помощью API.
  • Получить из локального хранилища, в которые данные были добавлены при прошлом запросе в API.
  • При работе с хранилищем все просто – данные там лежат уже в виде объектов и при запросе достаются оттуда, а вот для работы с API используются еще 2 сущности: адаптеры и сериализаторы.

  • Адаптеры задают правила работы с API, например получить все посты – GET /posts, а обновить пост – PUT /posts/1.
  • Сериализаторы разбирают json-ответ сервера и устанавливают формат json-запроса.
  • Контроллер Когда мы получили данные, мы можем приступить к их обработке. Именно в контроллере описываются вычисляемые свойства (computed properties). Контроллеры бывают нескольких видов:
  • Controller – обычный контроллер, например для статичных страниц.
  • ObjectController – для представления одного объекта.
  • ArrayController – для представления массива объектов, может иметь еще вложенный ObjectController для каждого объекта(например для вычисляемых свойств каждого объекта)
  • Представление После этого необходимо отрисовать наши данные. Тут нам приходят на помощь шаблоны, представления и компоненты. Давайте сначала поговорим о шаблонах – участках html кода в который вставляются наши данные. Они могут содержать партиалы, компоненты и представления.

    Теперь поговорим о представлениях и компонентах. Компоненты являются наследниками представлений, поэтому и то, и второе – это повторяемые участки кода. В связи с скорым переходом к версии 2.0 нам советуют использовать лишь компоненты.

    Components – целостные участки кода, отвечающие за одну функцию и которые будут использоваться в разных местах. Возьмем пример из жизни: мне необходимо было чтобы длинный текст автоматически сворачивался и появлялась кнопка «Развернуть». Именно для этого я использовал компоненты.

    Партиалы – это те же самые шаблоны, которые вставляются в другие шаблоны, к ним все это относится точно так же.

    Действия/события Теперь необходимо немного рассказать про действия и action bubbling – цепочку действий.
    Действия – то что происходит при определенных событиях(нажатию на элемент, отправку формы). Они описываются в контроллерах, маршрутах, представлениях, компонентах.
    Рассмотрим небольшой участок кода:

    // index.hbs {{post.title}}
    // index-controller.js App.IndexController = Ember.Controller.extend({ actions: { doSomething: function() { console.log("Вы только что нажали на заголовок") } } })
    При клике на заголовок это событие передастся в соответствующий контроллер и там обработается – в данном случае выведет надпись в консоль браузера.

    Action Bubbling Action bubbling – это передача события вверх по цепочке если не был найден обработчик в маршруте/контроллере.
    Пусть у нас будет такие маршруты, контроллеры и представления:

    // post-route.js App.PostsRoute = Ember.Route.extend({ actions: { doSomething: function() { // 1 } } }) // posts-controller.js App.PostsController = Ember.ArrayController.extend({ itemController: "post" actions: { doSomething: function() { // 2 } } }) // post-controller.js App.PostController = Ember.ObjectController.extend({ actions: { doSomething: function() { // 1 } } })

    // posts.hbs {{#each post in controller}} {{post.title}} {{/each}}

    При клике на название поста выполнится самое ближайшие действие – т.е. в PostController, если его нету – перейдет на уровень выше, и так дальше.

    Вот то же самое в виде схемы.

    В сети доступно огромное количество JavaScript библиотек и большинство из них выполняют свою работу неплохо, предоставляя разработчикам возможность взаимодействовать с DOM, выполняя задача необходимые для типичного веб-сайта. Но когда приходит время создать простой в управлении и поддержке код для одностраничного приложения на помощь нам приходят набор современных фреймворков, которые призваны справляться с данной задачей.

    Старые слова являются истиной: "используйте инструмент, который лучше всего подходит для поставленной задачи."

    Это вовсе не значит, что с библиотекой jQuery нельзя создать сайт работающий на подобии десктопного приложения, просто данная библиотека не создана для такого использования и у вас нет возможности применять связывание данных (data-binding), роутинг событий (event routing) и управление состоянием (state managment). Конечно к примеру вы можете добавить огромное количество плагинов, чтобы добиться подобного функционала, но начать работу с фреймворком, который был специально создан для выполнения этих задач, по моему мнению, гораздо более рационально. Старые слова являются истиной: "используйте инструмент, который лучше всего подходит для поставленной задачи."

    Ember поможет вам решить задачи описанные выше, он чем-то напоминает мне jQuery, позволяя начать работу с библиотекой довольно быстро и без лишних трудностей. Команда разработчиков сделала всё возможное, чтобы абстрагировать большинство сложностей связанных с построением модель/представление/контроллер (MVC - Model/View/Controller) приложений используя свой опыт создания высоконагруженных приложений.

    Я хочу помочь вам быстрее познакомиться с Ember.js, на протяжении нескольких статей, вы узнаете концепции данного фреймворка. Мы начнём с обычного введения (данный пост), после чего создадим полноценное приложение. Это здорово так как позволит мне взглянуть ещё раз на те концепции, которые я уже изучил и кто знает возможно по пути я узнаю новые техники и подходы! Также я сделаю всё возможное, чтобы команда Ember.js проверила данный материал и вероятно даже внесла свой небольшой вклад.

    Перед тем как мы продолжим, знайте что Ember.js предоставляет много волшебства для вас. Иногда вы можете обнаружить себя изучающим код и произносящим про себя "Хм? Как это работает?" Мне знакомо это чувство и я постараюсь помочь вам объяснить, но в тоже время не буду углубляться в особенности внутренней реализации фреймворка. Вместо этого, я постараюсь объяснить как использовать инструменты и интерфейс фреймворка для создания ваших собственных приложений.

    Так давайте же начнём.

    Основные концепции

    Ember.js не фреймворк для создания традиционных веб-сайтов.

    Первое что стоит понять, так это то что Ember.js не является фреймворком для создания традиционных веб-сайтов. Библиотеки на подобии jQuery и MooTools отлично подходят для этого. В том случае если вы планируете использовать Ember.js, предположу что вас интересует создания масштабируемого приложения, которое работает на подобии десктопного. Слоган фреймворка "фреймворк для создания амбициозных веб-приложений", что прямо говорит, что это не простая JavaScript библиотека к которой вы привыкли.

    Я упоминал до этого, что Ember использует паттерн MVC для организации и управления кодом. Если до этого вам не приходилось сталкиваться с разработкой основанной на MVC, вам следует прочитать об этом. У Nettuts+ есть . Что же касается тех кто уже знаком с данной концепцией, вы должны чувствовать себя тут как дома. Мне приходилось постоянно слышать, что сделать переход от Backbone к Ember.js довольно просто, так как Ember освобождает вас от написания большинства сложных вещей, при этом поддерживая организацию паттернов кода, к которым разработчики уже привыкли.

    Ember также сильно зависит от шаблонизации на стороне клиента. Он использует Handlebars библиотеку для шаблонизации , которая предоставляет выражения позволяющие создавать вам динамичные HTML шаблоны. Разработчик использующий Ember может привязать данные к подобным выражениям и динамично изменить отображение приложения на лету. К примеру, я могу создать шаблон, который получает массив в котором перечислены люди и отобразить неупорядоченный список с ними:

      {{#each people}}
    • Hello, {{name}}!
    • {{/each}}

    Обратите внимание на выражение "#each", которое работает, как цикл, обходя все элементы массива "people" и заменяя выражение "{{name}}" значением. Заметьте, двойные угловые скобки - знаки используемые для обозначения Handelbars выражений. Это всего лишь небольшой пример, мы разберём детали немного позже.

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

    Установка Ember

    Ember.js полагается на дополнительные библиотеки, поэтому вам понадобится копия jQuery и Handlebars . Секундочку, не говорил-ли я вам, что jQuery и Ember выполняют разные функции? Да действительно, но вот в чём дело: один из принципов команды разработчиков Ember, не изобретать колесо дважды. Поэтому они выбрали jQuery для того чтобы воспользоваться тем что jQuery делает лучше всего: работа с DOM. И это отлично, так как jQuery очень хорош в решении подобных задач. По этой же причине они выбрали Handelbars, это отличная библиотека шаблонизации, которая написана Yehuda Katz, одинм из главных разработчиков Ember.

    Самый простой способ получить все необходимые файлы Ember.js - скачать Starter Kit из Github репозитория. Это стартовый шаблон, каркас с которого вам следует начинать. К моменту написания данной статьи, он состоит из:

    • Ember 1.0 RC1
    • Handelbars 1.0 RC3
    • jQuery 1.9.1

    Также в вашем распоряжении есть html шаблон, со всем необходимым кодом включая нужные нам библиотеки (jQuery, Ember, итд.), помимо этого предоставляется пример Handelbars шаблона и "app.js", который включает код базового Ember приложения.

    Обратите однако внимание, app.js не является частью фреймворка. Это старый - добрый JavaScript файл; вы можете называть его как угодно. Мы будем использовать его для целей нашего туториала и скорее всего, в конце концов вы разделите JavaScript на несколько файлов, как и для любого другого приложения. Также для Ember нет определённой структуры каталогов и файлов.

    После того как вы изучите код Starter Kit, вам может показаться, что это код типичного веб-сайта. И тут вы пожалуй правы! Однако начав организацию, вы заметите, как создание приложение на Ember отличается.

    Слово о Ember

    Перед тем как начать работу с кодом, важно понять как Ember.js работает, также как и основные части фреймворка благодаря которым приложение функционирует. Давайте взглянем на эти части, а также разберём, как они взаимодействуют друг с другом.

    Шаблоны

    Шаблоны ключевая часть отвечающая за интерфейс пользователя. Как я упоминал прежде, Handelbars библиотека для клиентской части используемая Ember, предоставляемые библиотекой выражения используются для создания пользовательского интерфейса приложения. Вот пример:

    {{firstName}} {{lastName}}

    Обратите внимание, что выражения добавляются в вашу HTML разметку, затем Ember динамически изменит контент отображаемый на странице. В этом случае, плейсхолдеры {{firstName}} и {{lastName}} будут заменены данными приложения.

    Handlebars довольно мощный, благодаря гибкому API. Очень важно знать возможности предоставляемые данным шаблонизатором.

    Роутинг

    Роутер приложения помогает управлять состояниями нашего приложения.

    Роутер приложения помогает управлять состояниями приложения, также как и необходимыми ресурсами во время переходов пользователя. К примеру получение данных из модели, соединение контроллеров с представлением или отображения шаблонов.

    Всего этого можно добиться создав роут для определённой локации вашего приложения. Роуты определяют части приложения и соответствующий УРЛ для них. УРЛ ключевой идентификатор используемый Ember для того, чтобы понять какое состояние приложения следует показать пользователю.

    App.Router.map(function() { this.route("about"); // Takes us to "/about" });

    Поведение роута (то есть запрос данных из модели) обрабатывается экземпляром роута объекта Ember и запускается, когда пользователь посещает соответствующий УРЛ. К примеру запрос данных из модели, на вроде этого:

    App.EmployeesRoute = Ember.Route.extend({ model: function() { return App.Employee.find(); } });

    В этом случае, когда пользователь переходит по адресу "/empolyess", роут делает запрос к модели, чтобы получить список работников.

    Модели

    Объектное представление данных.

    Модель - объектное преставление данных, которые используются вашим приложением. Это может быть простой массив динамически получаемых данных от RESTful JSON API, благодаря Ajax запросам. Библиотека Ember Data предоставляет API для загрузки, назначения и обновления данных модели в вашем приложении.

    Контроллеры

    Контроллеры обычно используются для хранения и представления данных и атрибутов модели. Они действуют как прокси, предоставляя доступ к атрибутам модели, также возможность шаблонам отображать контент на экране. Вот почему шаблон всегда будет соединён с контроллером.

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

    Представление

    Представление в Ember.js управляют событиями взаимодействия пользователей и превращают их в события имеющие смысл для вашего приложения. Тем самым, если пользователь нажимает на кнопку удалить работника, представление отвечает за интерпретацию нативного события клика браузера и соответствующим образом обрабатывает его в контексте текущего состояния приложения.

    Соглашение об именовании

    Один из способов, благодаря которому Ember.js позволяет минимизировать количество необходимого кода и обрабатывать вещи за кулисами - соглашение об именовании. Как вы назовёте роуты (и ресурсы) влияет на именование контроллеров, моделей, представлений и шаблонов. К примеру, если я создам роут под названием "employees":

    App.Router.map(function() { this.resource("employees"); });

    Компоненты будут названы следующим образом:

    • Route object : App.EmployeesRoute
    • Controller : App.EmployeesController
    • Model : App.Employee
    • View : App.EmployeesView
    • Template : employees

    Использование соглашения о именовании имеет две цели. Во первых, в вашем распоряжении есть семантическое отношение между компонентами. Во вторых, Ember может автоматически создавать необходимые объекты, которые могут не существовать (то есть объект роута или контроллера) и связать их между собой в приложении. Это как раз то "волшебство", которое я упоминал ранее. По факту, это как раз то что Ember делает на глобальном уровне приложения, когда вы создаёте экземпляр объекта приложения (Application object):

    var App = Ember.Application.create();

    • Route object : App.ApplicationRoute
    • Controller : App.ApplicationController
    • View : App.ApplicationView
    • Template : application

    Вернёмся к роуту "employees", который я создал выше, что случится когда пользователь перейдёт по "/employees" в вашем приложении, Ember будет искать следующие объекты:

    • App.EmployeesRoute
    • App.EmployeesController
    • employees шаблон

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

    Обратите внимание на первый пример, я использовал имя состоящие из одного слова, "Employee", для определения модели. На то есть причина. Сама суть имя "Employees" указывает, что я работаю с 0 или большим количеством работников, поэтому это важно для создания модели, которая предоставляет гибкость при возвращении одного работника или нескольких работников. Однако имя модели состоящие из одного слова не является необходимостью в Ember, так как модель сама по себе ничего не знает о контроллерах, которые будет использовать данные позже. Поэтому вы обладаете гибкостью при именовании их, но для согласованности, придерживаться договорённостей об именовании в дальнейшем сделает управление кодом гораздо легче.

    Также, я выбрал метод resource() для определения роута, так как при таком сценарии, я скорее всего буду иметь вложенные роуты для страниц управления информацией о работнике. Мы поговорим о вложенности позже в серии данных статей.

    Ключевое преимущество использование соглашения об именовании, Ember может с лёгкостью управлять и связывать компоненты между собой, вам не придётся самостоятельно, вручную описывать взаимосвязи в коде.

    Подробности о соглашении об именовании Ember можно найти на сайте проекта и вам следует ознакомиться с этой информацией .

    Далее: создание приложения

    В следующей части мы начнём работать с кодом и создадим основу нашего приложения.

    Мы ознакомились с основными концепциями Ember и обсудили ключевые аспекты фреймворка. В следующей части мы начнём работу с кодом и создадим основу нашего приложения. Опять же повторюсь, рекомендую ознакомиться с документацией Handlebars, чтобы разобраться в синтаксисе выражений. Также если вы всерьёз заинтересовались Ember, следите за обновлениями на Tuts+ Premium , скоро появится курс, в котором мы создадим полноценное приложение основанное на Ember!

    Как я упоминал в начале статьи, команда разработчиков Ember.js во главе с

  • Программирование
    • Перевод

    В наши дни сложные 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,

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

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

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

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

    Теперь у нас есть модель и контроллер – осталось только написать представление. Помните, я говорил, что представление – визуальная часть вашего приложения? Значит это будет находится в файле index.html . Давайте сначала напишем наше представление, а потом обсудим его. Прямо под тег H1 добавьте следующее:
    {{#view Ember.Button target="Welcome.booksController" action="loadBooks"}} Load Books {{/view}} {{#collection contentBinding="Welcome.booksController" tagName="ul"}} {{content.title}} - {{content.author}}, {{content.genre}} {{/collection}}

    Одна из замечательных особенностей 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 шанс. Вы можете