Если вы когда-нибудь создавали директивы Angular, то вы, вероятно, использовали в качестве селектора конструкцию, в которой используются скобки: ([])
. Такой подход, хотя чаще всего применяется именно он, не является единственно возможным. На самом деле, селекторы, используемые в директивах, дают программисту широкий простор для творчества. Для того чтобы продемонстрировать эту идею в действии, в материале, перевод которого мы публикуем сегодня, рассмотрена методика создания директивы, предназначенной для работы с внешними ссылками, которые имеются в шаблоне. В частности, речь пойдёт о том, как можно находить обычные HTML-элементы, и, при необходимости, исключать из выборки некоторые из них, используя псевдокласс :not
.
Директива 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-код, то можно будет увидеть следующее:
HTML-код навигационного блока после применения директивы
Это именно то, что нам нужно. Директива работает без необходимости применения дополнительных селекторов атрибутов.
Итоги
Из этого материала вы узнали о том, что, при работе с директивами Angular, необязательно использовать селекторы атрибутов. Здесь мы сначала исследовали директиву ngForm
, после чего использовали полученные знания для создания собственной директивы, предназначенной для работы с внешними ссылками. Надеемся, эта методика вам пригодится.
Уважаемые читатели! Если вам известны какие-нибудь неочевидные приёмы разработки веб-проектов с использованием Angular — просим о них рассказать.
Автор: ru_vds