Angular: неочевидные возможности селекторов директив

в 9:28, , рубрики: angular, Блог компании RUVDS.com, разработка, Разработка веб-сайтов

Если вы когда-нибудь создавали директивы Angular, то вы, вероятно, использовали в качестве селектора конструкцию, в которой используются скобки: ([]). Такой подход, хотя чаще всего применяется именно он, не является единственно возможным. На самом деле, селекторы, используемые в директивах, дают программисту широкий простор для творчества. Для того чтобы продемонстрировать эту идею в действии, в материале, перевод которого мы публикуем сегодня, рассмотрена методика создания директивы, предназначенной для работы с внешними ссылками, которые имеются в шаблоне. В частности, речь пойдёт о том, как можно находить обычные HTML-элементы, и, при необходимости, исключать из выборки некоторые из них, используя псевдокласс :not.

Angular: неочевидные возможности селекторов директив - 1

Директива ngForm

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

@Directive({
  selector: 'form:not([ngNoForm]):not([formGroup]),ngForm,ng-form,[ngForm]',
})

Тут стоит обратить внимание на следующее:

  • Директива может быть рассчитана на несколько селекторов, которые можно перечислять через запятую.
  • Здесь можно смешивать целевые HTML-элементы (наподобие <form>) c HTML-атрибутами (вроде ngForm).
  • Для исключения каких-то элементов из выборки можно использовать псевдокласс :not.

Создание директивы для работы с внешними ссылками

Под внешней ссылкой мы понимаем тег <a>, у которого нет директивы routerLink. Учитывая то, что мы выяснили, анализируя предыдущий пример, соответствующий селектор можно описать так:

@Directive({
  selector: 'a:not([routerLink])',
})

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

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

Результаты применения директивы к внешним ссылкам должны выглядеть так:

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

Обе эти цели достижимы благодаря использованию @HostBinding():

@Directive({
  selector: 'a:not([routerLink])'
})
export class ExternalLinkDirective {
  @HostBinding('rel')
  @Input()
  rel = 'noopener';

  @HostBinding('target')
  @Input()
  target = '_blank';
}

Обратите внимание на то, что тут мы, кроме прочего, декорировали свойства с помощью декоратора @Input(), что, при необходимости, открывает возможности для переопределения.

Ещё одна допустимая реализация подобного решения может заключаться в использовании декоратора @Attribute(). Такой подход даст небольшое увеличение в производительности, так как, в отличие от декоратора @Input(), при использовании @Attribute() значения соответствующих свойств вычисляются лишь один раз, то есть, не производится постоянной проверки свойств rel и target в цикле проверки изменений.

Подробности об этой методике можно почитать здесь.

Тестирование директивы

Создадим простой навигационный блок, содержащий ссылки, ведущие на внешние ресурсы:

<nav>
  <a href="https://google.com">Google</a>
  <a href="https://bing.com">Bing</a>
  <a href="https://forbes.com">Forbes</a>
</nav>

Если, с помощью инструментов разработчика Chrome, посмотреть соответствующий HTML-код, то можно будет увидеть следующее:

Angular: неочевидные возможности селекторов директив - 2

HTML-код навигационного блока после применения директивы

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

Итоги

Из этого материала вы узнали о том, что, при работе с директивами Angular, необязательно использовать селекторы атрибутов. Здесь мы сначала исследовали директиву ngForm, после чего использовали полученные знания для создания собственной директивы, предназначенной для работы с внешними ссылками. Надеемся, эта методика вам пригодится.

Уважаемые читатели! Если вам известны какие-нибудь неочевидные приёмы разработки веб-проектов с использованием Angular — просим о них рассказать.

Автор: ru_vds

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js