Информационный портал по безопасности. Жизненный цикл компонента. Соглашение об именовании

Faq 19.03.2019
Faq

В сети доступно огромное количество 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 библиотек, предназначенных для манипулирования DOM-ом. Однако когда речь заходит о необходимости построения одно-страничного приложения, многие фрэймворки сдуваются.

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

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

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

Давайте же приступим!

Основы

Первое, что вы должны понять, так это то, что Ember.js - это фрэймворк для создания нетрадиционных сайтов. Такие фрэймворки, как jQuery и Mootools, больше подходят для классических сайтов. Приложения, создаваемые на основе Ember.js, больше похожи на настольные приложения.

Как я уже упоминал ранее, Ember.js использует MVC в качестве системы распределения кода. Если совсем ничего не знаете о MVC, то вам нужно прочитать самую простую статью, где описывается работа по данной схеме. Если вы когда-то использовали Backbone.js, то понять Ember.js вам не составит труда.

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

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

Ключевое слово #each означает обычный цикл, в котором будут прокручиваться записи из переменной people. Выражениями типа {{name}}, мы будем извлекать нужную информацию. Более сложные примеры, мы разберём позже.

Handlebars - это действительно хороший шаблонизатор, который может использоваться отдельно от Ember.js. На их официальном сайте вы можете найти дополнительную информацию.

Настройка Ember

Ember.js работает на основе других библиотек, так что вам нужно будет подключить jQuery и Handlebars . Стоп! Не я ли ранее сказал что jQuery и Ember предназначены для разных целей? Да, но на самом деле ситуация выглядит несколько иначе: команда разработчиков решила не изобретать колесо. Они выбрали jQuery, для того чтобы с его помощью делать то, что у него лучше всего получается: манипулировать DOM-ом. Подобными мыслями они руководствовались при подключении Handlebars.

На самом деле, вам не нужно бегать по разным сайтам за нужными ссылками библиотек. Всё нужное вы сможете найти на странице Ember.js на гитхабе. Качаем Starter-kit и получаем:

  • Ember 1.0 RC1
  • Handlerbars 1.0 RC3
  • jQuery 1.9.1

Все эти файлы сразу распределены по папкам. Для нашего приложения лучше всего создать собственный файл. Назовём его app.js:

Возможности Ember

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

Шаблоны

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

{{firstName}} {{lastName}}

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

Маршруты

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

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

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

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

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

Как только пользователь перейдёт по адресу “/employees”, то маршрутизатор сделает обращение к модели и вытащит список работников.

Модели

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

Контроллеры

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

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

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

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

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

Правила именования

Используя Ember.js, можно сократить количество кода за счёт установленной для себя системы именования объектов. В зависимости от того, как вы назовёте маршрут, зависит имя контроллера, модели, представления и шаблона. К примеру, мы создали маршрут “employees”:

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

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

  • Маршрут: App.EmployeesRoute
  • Контроллер: App.EmployeesController
  • Модель: App.Employee
  • Представление: App.EmployeesView
  • Шаблон: employees

Подобное правило именования удобно по нескольким причинам. Во-первых, мы сразу же видим семантическую связь между компонентами. Во-вторых, Ember сможет самостоятельно создать объекты, которых будет не хватать. Всё это возможно при инициализации приложения:

Var App = Ember.Application.create();

Одна строчка задаёт отношения между контроллерами, объектами, представлениями и шаблонами:

  • Маршрут: App.ApplicationRoute
  • Контроллер: App.ApplicationController
  • Представление: App.ApplicationView
  • Шаблон: application

При навигации на адрес “/employees”, Ember активирует другие ресурсы:

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

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

Что дальше?

На сегодня всё. Мы познакомились с Ember.js и её компонентами. В следующих частях этой серии статей займёмся практическим использованием данной библиотеки и на практике попробуем многое из того, что предоставляет нам 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 , доступного в классе компонента.



Рекомендуем почитать

Наверх