Статьи

Понимание компонентов в Ember 2

Эта статья была рецензирована Эдвином Рейносо и Нильсоном Жаком . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!

Компоненты являются жизненно важной частью приложения Ember. Они позволяют вам определять свои собственные, специфичные для приложения HTML-теги и реализовывать их поведение с помощью JavaScript. Начиная с Ember 2.x компоненты будут заменять представления и контроллеры (которые устарели) и являются рекомендуемым способом создания приложения Ember.

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

Если вы хотите узнать больше о том, почему маршрутизируемые компоненты заменяют контроллеры и представления, посмотрите это короткое видео от членов основной команды Ember Иегуды Каца и Тома Дейла.

Приложение Tab Switcher

Чтобы получить более глубокое понимание компонентов Ember, мы tab-switcher виджет tab-switcher . Это будет включать набор вкладок со связанным контентом. Нажатие на вкладку отобразит содержимое этой вкладки и скроет содержимое других вкладок. Достаточно просто? Давайте начнем.

Как всегда, вы можете найти код этого руководства в нашем репозитории GitHub или в Ember Twiddle , если вы хотите поэкспериментировать с кодом в своем браузере.

Анатомия угольного компонента

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

 {{tab-switcher}}{{/tab-switcher}} 

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

Наш основной компонент Ember будет tab-switcher . Обратите внимание, я сказал основной компонент, потому что у нас будет несколько компонентов. Вы можете использовать компоненты в сочетании с другими. Вы даже можете иметь компоненты, вложенные в другой родительский компонент. В случае нашего tab-switcher у нас будет один или несколько компонентов tab-item например:

 {{#each tabItems as |tabItem| }} {{tab-item item=tabItem setSelectedTabItemAction="setSelectedTabItem" }} {{/each}} 

Как видите, компоненты также могут иметь атрибуты, как и нативные элементы HTML.

Создать проект Ember 2.x

Чтобы следовать этому туториалу, вам нужно создать проект EMber 2.x. Вот как:

Ember устанавливается с помощью npm. Об учебнике по npm вы можете посмотреть здесь .

 npm install -g ember-cli 

На момент написания этого будет тянуть в версии 1.13

 ember -v => version: 1.13.8 

Затем создайте новое приложение Ember:

 ember new tabswitcher 

Перейдите в этот каталог и отредактируйте файл bower.json включив в него последнюю версию Ember, ember-data и ember-load-initializer:

 { "name": "hello-world", "dependencies": { "ember": "^2.1.0", "ember-data": "^2.1.0", "ember-load-initializers": "^ember-cli/ember-load-initializers#0.1.7", ... } } 

Вернемся в терминал запустить:

 bower install 

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

Следующий запуск сервера разработки Ember CLI:

 ember server 

Наконец, перейдите по адресу http: // localhost: 4200 / и проверьте версию консоли вашего браузера.

Создание компонента «Переключатель вкладок»

Давайте создадим компонент переключателя вкладок, используя встроенный генератор Ember:

 ember generate component tab-switcher 

Это создаст три новых файла. Один — это файл Handlebars для нашего HTML ( app/templates/components/tab-switcher.hbs ), второй — файл JavaScript для нашего класса компонентов ( app/components/tab-switcher.js ), последний — тест файл ( tests/integration/components/tab-switcher-test.js ). Тестирование компонента выходит за рамки данного руководства, но вы можете прочитать об этом подробнее на сайте Ember .

Теперь запустите ember server чтобы загрузить сервер и перейти по адресу http: // localhost: 4200 / . Вы должны увидеть приветственное сообщение под названием «Добро пожаловать в Ember». Так почему же не появляется наш компонент? Ну, мы еще не использовали его, поэтому давайте сделаем это сейчас.

Использование компонента

Откройте шаблон app/templates/application.hbs . Добавьте следующее после тега h2 чтобы использовать компонент.

 {{tab-switcher}} 

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

Это все еще не отображает никакого контента на экране, хотя. Это потому, что сам компонент не имеет никакого контента для показа. Мы можем изменить это, добавив следующую строку в файл app/templates/components/tab-switcher.hbs ( app/templates/components/tab-switcher.hbs ):

 <p>This is some content coming from our tab switcher component</p> 

Теперь, когда страница перезагрузится (что должно произойти автоматически), вы увидите текст выше. Захватывающие времена!

Создать компонент элемента вкладки

Теперь, когда мы настроили наш основной компонент tab-switcher , давайте создадим несколько компонентов tab-item для размещения внутри него. Мы можем создать новый компонент tab-item следующим образом:

 ember generate component tab-item 

Теперь измените файл app/templates/components/tab-item.hbs для нового компонента ( app/templates/components/tab-item.hbs ) на:

 <span>Tab Item Title</span> {{yield}} 

Теперь давайте вложим три tab-items в наш основной компонент tab-switcher . Измените файл шаблона tab-switcher ( app/templates/components/tab-switcher.hbs ) на:

 <p>This is some content coming from our tab switcher component</p> {{tab-item}} {{tab-item}} {{tab-item}} {{yield}} 

Как упоминалось выше, помощник yield будет отображать любой шаблон Handlebars, который передается нашему компоненту. Однако это полезно только в том случае, если мы используем tab-switcher в форме блока. Так как мы не являемся, мы можем полностью удалить помощник yield .

Теперь, когда мы просматриваем браузер, мы видим три tab-item components , все из которых говорят «Название элементов табуляции». Наш компонент сейчас довольно статичен, поэтому давайте добавим некоторые динамические данные.

Добавление динамических данных

Когда запускается приложение Ember, маршрутизатор отвечает за отображение шаблонов, загрузку данных и настройку состояния приложения. Это делается путем сопоставления текущего URL с указанными вами маршрутами. Давайте создадим маршрут для нашего приложения:

 ember generate route application 

Ответьте «нет» на вопрос командной строки, чтобы избежать перезаписи существующего файла application.hbs . Это также сгенерирует файл app/routes/application.js . Откройте это и добавьте свойство модели:

 export default Ember.Route.extend({ model: function(){ }); }); 

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

 import Ember from 'ember'; export default Ember.Route.extend({ model: function(){ var tabItems = [ { title: 'Tab 1', content: 'Some exciting content for the tab 1' }, { title: 'Tab 2', content: 'Some awesome content for the tab 2' }, { title: 'Tab 3', content: 'Some stupendous content for the tab 3' } ]; return tabItems; } }); 

Затем измените файл шаблона tab-switcher ( app/templates/components/tab-switcher.hbs ) на:

 {{#each tabItems as |tabItem| }} {{tab-item item=tabItem }} {{/each}} 

Затем измените содержимое файла app/templates/components/tab-item.hbs ( app/templates/components/tab-item.hbs ) на:

 <span>{{item.title}}</span> {{yield}} 

Наконец, измените использование tab-switcher в файле application.hbs на:

 {{tab-switcher tabItems=model}} 

Это демонстрирует, как передать свойства компоненту. Мы сделали свойство item доступным для шаблона компонента tab-item . После обновления страницы вы должны увидеть заголовки элементов вкладки, отражающие данные моделей.

Добавление взаимодействий с помощью действий

Теперь давайте удостоверимся, что когда пользователь нажимает на заголовок tab-item , мы отображаем содержимое этого tab-item . Измените файл шаблона tab-switcher ( app/templates/components/tab-switcher.hbs ) на:

 {{#each tabItems as |tabItem| }} {{tab-item item=tabItem setSelectedTabItemAction="setSelectedTabItem" }} {{/each}} <div class="item-content"> {{selectedTabItem.content}} </div> 

Это изменение предполагает, что у нас есть свойство tabItem в компоненте tab-switcher . Это свойство представляет текущий выбранный tab-item . В настоящее время у нас нет такой собственности, поэтому давайте разберемся с этим.

Внутри обычного шаблона действие всплывает до контроллера. Внутри шаблона компонента действие всплывает до класса компонента. Он больше не поднимается вверх по иерархии.

Нам нужен способ для отправки действий щелчка компоненту tab-switcher . Это должно произойти после нажатия любого из его дочерних компонентов tab-item . Помните, я говорил, что действия отправляются классу компонента, а не дальше по иерархии.

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

Простой обходной путь — добавить действие в шаблон tab-switcher ( app/templates/components/tab-switcher.hbs ) следующим образом:

 {{#each tabItems as |tabItem| }} <div {{action "setSelectedTabItem" tabItem}} > {{tab-item item=tabItem setSelectedTabItemAction="setSelectedTabItem" }} </div> {{/each}} <div class="item-content"> {{selectedTabItem.content}} </div> 

И чтобы изменить файл класса tab-switcher ( app/components/tab-switcher.js ), чтобы он выглядел следующим образом

 export default Ember.Component.extend({ actions: { setSelectedTabItem: function(tabItem){ this.set('selectedTabItem', tabItem); } } }); 

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

Тем не менее, этот обходной путь не учитывает тот факт, что действие только всплывает до класса компонента, поэтому давайте сделаем это таким образом. Сохраните изменения в app/components/tab-switcher.js , но верните app/templates/components/tab-switcher.hbs обратно в прежнее состояние:

 <div class="item-content"> {{selectedTabItem.content}} </div> {{#each tabItems as |tabItem| }} {{tab-item item=tabItem setSelectedTabItemAction="setSelectedTabItem" }} {{/each}} 

Теперь давайте изменим шаблон tab-item на:

 <span {{action "clicked" item }}>{{item.title}}</span> {{yield}} 

И файл класса tab-item для:

 export default Ember.Component.extend({ actions:{ clicked: function(tabItem){ this.sendAction("setSelectedTabItemAction", tabItem); } } }); 

Здесь вы можете видеть, что мы добавили обработчик действий для обработки кликов на заголовке tab-item . Это отправляет действие от компонента tab-item его родителю, компоненту tab-switcher . Действие поднимает иерархию вместе с параметром, а именно tabItem которому мы щелкнули. Это делается для того, чтобы его можно было установить в качестве текущего tab-item в родительском компоненте.

Обратите внимание, что мы используем свойство setSelectedTabItemAction в качестве действия для отправки. Это не фактическое имя действия, которое отправляется, а значение, содержащееся в свойстве — в этом случае setSelectedTabItem , который является обработчиком в родительском компоненте.

Вывод

И это подводит нас к концу этого введения в компоненты Ember. Надеюсь, вам понравилось. Преимущества продуктивности от использования повторно используемых компонентов в ваших проектах Ember нельзя преуменьшить (и, в действительности, во всех ваших проектах). Почему бы не попробовать? Исходный код этого руководства доступен на GitHub .

Вы уже используете компоненты в Ember? Какой у вас был опыт до сих пор? Я хотел бы услышать от вас в комментариях.