Традиционно веб-разработчики имели ограниченный выбор, когда дело касалось тегов разметки в HTML. Мы в основном были ограничены тем, что определяет W3C. Поскольку веб-приложения становятся все более сложными, возникает растущая потребность в возможности создавать собственные теги для представления областей функциональности внутри них. В настоящее время в W3C разрабатываются спецификации, направленные на удовлетворение этой потребности. Спецификация Custom Elements определяет способ создания пользовательских тегов с их собственными атрибутами, создавая так называемые веб-компоненты. В Ember есть версия веб-компонентов, которую он уместно называет Компонентами (Components), разработанная для реализации спецификации W3C Custom Element. Компоненты Ember позволяют нам создавать повторно используемые элементы в наших приложениях с именами и свойствами, которые наилучшим образом отражают их функциональность.
С момента публикации моего последнего поста, в котором упоминался вымышленный интернет-магазин газировки, я получил несколько вопросов о газировке со вкусом бекона. Можем ли мы ее предоставить? Еще как можем. В этом посте мы будем использовать компонент Ember для создания списка клиентов для нашего интернет-магазина газировки. Клиенты, которые запросили образец газировки со вкусом бекона, будут называться пробными клиентами. Клиенты, которые подписались на ежемесячную доставку своей порции, будут называться подписчиками. Мы будем использовать Firebase и Ember Data для хранения наших клиентов (подробности об интеграции этих технологий вы можете прочитать в первом посте о магазине газировки). Мы создадим страницу для отображения пробных клиентов и другую страницу для отображения подписчиков. Мы будем использовать один и тот же компонент для каждого списка и задавать свойства компонента для отображения разных столбцов для пробных клиентов и подписчиков. Это поможет сделать нашу разметку чистой и семантической.
Если вы только начинаете работать с Ember.js, перейдите к этому посту и установите все необходимое. Если вы хотите сразу приступить к работе и посмотреть код для примера, который мы создадим в этом посте, вы найдете его в этом репозитории Github.
Прежде чем углубиться в наш пример, давайте посмотрим, как устроены Компоненты. Компоненты состоят из двух файлов:
**Файл шаблона (.hbs)** – Этот файл HTMLBars содержит разметку, определяющую пользовательский интерфейс компонента. По умолчанию он будет отображен в тег `div`, но мы также можем определить другой тег для элемента в файле JavaScript компонента. Шаблон также может включать другие компоненты.
**Файл JavaScript – **Этот файл можно использовать для добавления свойств и поведения компоненту. Поведение обычно задается с помощью действий (Actions).
Давайте начнем с создания нового приложения Ember с помощью Ember CLI:
Измените файл `bower.json`, чтобы обновить зависимости ember и ember-data до версии 2.0.0, так как Ember CLI еще не полностью обновлен для Ember 2.0:
Запустите `bower install` и, если появится запрос, обязательно обновите Ember до последней версии (на данный момент 2.0.2):
Откройте `app/templates/application.hbs` и измените сообщение «Welcome to Ember!» на «Customer List Demo»:
Мы будем отображать данные в таблицах, а стандартные HTML-таблицы — не самое приятное зрелище. Давайте добавим легкую поддержку стилей, установив Picnic CSS. Выполните эту команду в терминале:
Отредактируйте `ember-cli-build.js`, добавив шаг для импорта `picnic.min.css` в наше приложение Ember:
Функция импорта добавляет содержимое `picnic.min.css` в файл `vendor.css` нашего приложения во время сборки, что делает содержащиеся в нем стили доступными везде в нашем приложении.
Мы также будем работать с некоторыми датами в нашем приложении, поэтому давайте установим несколько хелперов Ember для замечательной библиотеки **moment.js**. Это облегчит отображение отформатированных дат и продолжительности времени в наших шаблонах Ember. Выполните эти команды в терминале:
Первая команда устанавливает аддон `ember-moment`, а вторая команда генерирует хелперы, которые мы будем использовать в шаблонах наших компонентов.
Есть еще одна вещь, которую нам нужно добавить в наш проект, прежде чем мы начнем добавлять клиентов — это Firebase. Перейдите на сайт Firebase и создайте бесплатный аккаунт, если у вас его еще нет. После входа в систему создайте новое приложение Firebase и дайте ему любое имя и URL-адрес приложения. Просто обязательно запишите URL-адрес приложения, так как он понадобится нам при настройке аддона Firebase для Ember Data.
Обновите `config/environment.js`, чтобы задать URL-адрес Firebase для URL-адреса приложения Firebase, которое мы создали ранее:
Прежде чем мы сможем отображать клиентов в Компоненте, нам нужно добавить модель клиента и загрузить некоторых клиентов в наше приложение Firebase. Используйте Ember CLI для генерации модели клиента:
Замените `app/models/customer.js` следующим кодом:
Большая часть этого — стандартные определения атрибутов Ember Data. Выделенные строки создают вычисляемое свойство, которое обновляется при каждом изменении `subscriptionDate` или `subscriptionDuration`. Оно использует moment.js для вычисления даты истечения срока подписки. Мы будем использовать это в нашем компоненте списка клиентов для отображения того, сколько времени осталось в подписке клиента.
Теперь мы воспользуемся консолью JavaScript в нашем браузере, чтобы добавить нескольких клиентов в Firebase. Для этого шага вам понадобится Ember Inspector для Chrome или Firefox, поэтому установите его, если у вас его нет. Откройте приложение по адресу http://localhost:4200, если оно у вас еще не открыто, а затем откройте инструменты разработчика в браузере. Перейдите на вкладку Ember, нажмите Routes, а затем нажмите ссылку `>$E` рядом с маршрутом index:
Теперь мы можем использовать `$E` для ссылки на маршрут в консоли JavaScript и использовать его для добавления некоторых данных в Firebase с помощью Ember Data. Выполните следующие строки в консоли JavaScript, чтобы добавить пару пробных клиентов и нескольких подписчиков:
Проверьте свое приложение Firebase, чтобы убедиться, что все 4 записи были успешно синхронизированы, прежде чем продолжить.
Чтобы получить хорошее представление об очистке кода и возможности повторного использования, которые мы получаем от компонентов, давайте начнем без них. Мы создадим маршрут и шаблон, как обычно делаем в приложении без компонентов, а затем посмотрим, почему нам может потребоваться рефакторинг. Давайте начнем с создания маршрута для отображения наших пробных клиентов:
Выделенные строки — это фильтр Ember Data, который будет обновляться каждый раз при создании модели. Он возвращает только тех клиентов, которые не подписаны. Теперь давайте отредактируем шаблон `app/templates/trials.hbs`, чтобы отобразить таблицу со списком имен, местоположений и дат регистрации пробных клиентов:
Отлично, это работает. На этом этапе мы могли бы повторить весь этот процесс для подписчиков, включая дублирование всей этой разметки шаблона. Но мы не будем этого делать, потому что будем следовать принципу DRY (Не повторяйся). Вместо этого мы создадим компонент для представления списка клиентов, который сможет отображать определенную информацию для пробных клиентов и другую информацию для подписчиков. Затем мы будем использовать это в шаблонах для пробных клиентов и подписчиков.
Ember CLI делает создание компонентов очень простым. Для компонентов есть генератор, точно так же, как и генераторы, которые мы использовали для моделей и маршрутов. Давайте создадим компонент списка клиентов:
Эта команда генерирует файл шаблона и файл JS для компонента. Скопируйте разметку таблицы из `app/templates/trials.hbs` в `app/templates/components/customer-list.hbs` и измените цикл #each для перебора списка `customers` вместо `model`:
Теперь вернитесь к шаблону `trials.hbs` и замените разметку таблицы объявлением этого компонента:
Здесь мы передаем клиентов из `model` маршрута trial в компонент customer-list, используя атрибут с именем `customers`, который мы использовали в шаблоне компонента выше. Сохраните свою работу и проверьте http://localhost:4200/trials, чтобы убедиться, что все по-прежнему работает (если страница у вас все еще открыта, она перезагрузится автоматически). Теперь давайте поработаем над отображением наших подписчиков.
Мы начнем с создания маршрута для отображения подписчиков:
Затем мы настроим хук `model` в `app/routes/subscribers.js`, используя фильтр, как мы это делали для пробных клиентов:
Теперь отредактируйте `app/templates/subscribers.hbs` так, чтобы он содержал компонент customer-list, точно так же, как и компонент для пробных клиентов:
Посмотрите на http://localhost:4200/subscribers. Это отлично работает и отображает базовую информацию о подписчиках, так же как и о пробных клиентах. Однако у нас есть больше информации, которую мы можем отображать для подписчиков, поэтому давайте отредактируем шаблон компонента для ее поддержки. Отредактируйте шаблон `customer-list.hbs` так, чтобы он выглядел следующим образом:
Два выделенных раздела добавляют некоторую информацию, специфичную для подписчиков, только в том случае, если свойство `showSubscriberInfo` установлено в `true` для компонента. Мы можем легко установить это, отредактировав объявление компонента в `subscribers.hbs`:
Сохраните свою работу и проверьте http://localhost:4200/trials и http://localhost:4200/subscribers, чтобы увидеть разницу между отображением пробных клиентов и подписчиков. Вот как должны выглядеть подписчики:
В этом посте мы создали список клиентов для покупателей изысканной, ремесленной, сделанной вручную газировки со вкусом бекона. Мы смогли избавиться от дублирования кода, создав повторно используемый компонент в Ember. Этот компонент — то, что мы можем легко использовать в будущих проектах, и с небольшой работой мы могли бы даже поделиться им с сообществом Ember в качестве аддона. Вот еще несколько вещей, которые вы можете попробовать с тем, что мы создали:
— Создайте компонент customer-row, который можно использовать внутри шаблона customer-list. (Подсказка: вам потребуется настроить элемент, в который этот компонент рендерится)
— Добавьте кнопку «Подписаться» в список пробных клиентов и используйте действие (action) для обновления клиента при нажатии на эту кнопку.
— Попробуйте упаковать ваши компоненты как аддон Ember.
— Попробуйте некоторые компоненты из Ember VCL
— Если вас беспокоят строгие предупреждения Content Security Policy в консоли JavaScript, здесь есть информация о том, как их очистить.
Я очень рад за Ember и еще больше рад видеть то, что вы создадите с его помощью. Поделитесь этим со мной в Twitter @brentschooley или напишите мне на brent@twilio.com.