Использование директивы несколько раз для элемента
Объяснение того, как Angular обрабатывает элементы, для которых директива создается более одного раза
Директивы в Angular пригодятся, когда мы хотим преобразовать или настроить внешний вид элемента. Кроме того, использование директив лучше для абстракции, поскольку вся логика реализации абстрагируется в реализации директивы и может использоваться для любого количества элементов, просто добавляя селекторы директив вместе с входами, если они есть.
В этой статье я собираюсь объяснить сценарий, в котором директива используется более одного раза в элементе, и как Angular обрабатывает такие случаи.
Как обычно, давайте рассмотрим простой пример. Я собираюсь создать директиву square
, которая обновляет значение хост-элемента до квадрата его значения. Вот простая реализация этой директивы:
И чтобы использовать это в элементе ввода, вот пример кода, который выглядит так:
Итак, мы устанавливаем значение 10 для ввода, но во время инициализации вызывается директива appSquare
и обновляет значение при вводе до квадрата его значения, 100.
Вот как выглядит ввод после рендеринга:
Теперь, например, если мы хотим возвести в квадрат возведенное в квадрат значение, например, если мы передаем 10
, тогда входные данные должны быть обновлены с помощью 10000
Итак, можем ли мы использовать appSqaure
directive дважды для этого элемента, чтобы достичь этого?
Давайте разберемся в этом сейчас, обновив приведенный выше пример.
После обновления ввода шаблон теперь выглядит так:
И результат, отображаемый в пользовательском интерфейсе, выглядит следующим образом:
Да, значение осталось прежним.
Что здесь происходит?
Давайте сделаем шаг назад и поймем, как работает процесс компиляции Angular, когда директива добавляется к элементу более одного раза.
Во время процесса компиляции Angular компилятор Angular выполняет определение каждого элемента и устанавливает атрибуты для нативного элемента. И реализация этой части показана ниже.
Исходный код: https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/dom_renderer.ts#L184
Поскольку атрибуты установлены как Map
в собственном элементе, невозможно определить один и тот же атрибут более одного раза (поскольку ключи уникальны в Map, если они являются литералами, и в этом случае они сравниваются по значению).
Поскольку Angular выполняет цикл по всем атрибутам, определенным для элемента, в порядке их размещения, сохраняется самый последний атрибут типа в элементе.
Давайте изменим предыдущий пример директивы, чтобы он принимал входное значение и передавал разные значения для каждого экземпляра директивы. В этом случае приоритет будет отдан последней директиве.
А теперь давайте обновим шаблон, чтобы передать значения для обоих экземпляров директивы. Поскольку у нас есть @Input
, определенный с тем же именем, что и селектор директив, нам не нужно передавать дополнительные входные данные, и вместо этого мы можем просто передать значение декларации directive
самостоятельно (он выполняет обе обязанности как селектор директивы и декоратор ввода).
Вот как это выглядит:
Если мы сейчас запустим наше приложение, то увидим это в консоли:
Как я сказал выше, более поздний экземпляр директивы удаляет предыдущий, что можно увидеть в приведенном выше примере.
Вот и все. Спасибо за прочтение! Следуйте за мной на Medium, чтобы увидеть больше интересных статей.