En

JazzTeam Software Development Company

Agile Java Development

AngularJS директивы. Жизненный цикл

О мануале

Данный мануал будет полезен разработчику, который уже знаком с основами AngularJS фреймворка и уже знает, как создавать свои директивы, знает, что такое объект определения директивы и его свойства, которые подробно описаны в официальной документации.

В этом мануале мы детально рассмотрим жизненный цикл директив, разберём подробнее функции объекта определения директивы (link, compile, controller), определим порядок их выполнения и приведем особенности их использования.

Поехали!

При написании директивы для управления ее поведением можно использовать любое из следующих свойств объекта определения директивы: compile, link, controller. В них мы можем манипулировать разметкой, работать с дочерними элементами, реализовывать бизнес логику, присоединить обработчики событий и назначить наблюдателей (observers и watches) к атрибутам.

Compile - это функция, которая преобразует шаблон DOM в angular приложение. Не все директивы выполняют преобразование шаблона, поэтому она часто не используется.

Link - это функция, которая отвечает за регистрацию DOM-обработчиков событий и за обновление DOM. Чаще всего здесь находится большая часть логики директивы.

Controller - это функция конструктора контроллера директивы.

Функции Compile и Link будут возвращать либо объект с функциями preLink и postLink, либо просто возвращать функцию, которая будет являться postLink.

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

Порядок выполнения

Для начала рассмотрим порядок выполнения функций controller, compile, preLink, postLink при инициализации директивы.

Для одной директивы

Рассмотрим пример директивы log, которая делает вывод в консоль переданной строки на различных этапах своей загрузки.

HTML разметка:

JS код объявления директивы:

Вывод консоли будет следующим:

some-div (compile)
some-div (controller)
some-div (pre-link)
some-div (post-link)

На данном примере мы видим, что сначала выполняется compile, затем controller, далее preLink, и последняя postLink.

Для вложенных директив

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

HTML разметка:

Вывод консоли будет выглядеть так:
// The compile phase
parent (compile)
..first-child (compile)
..second-child (compile)

// The link phase
parent (controller)
parent (pre-link)
..first-child (controller)
..first-child (pre-link)
..first-child (post-link)
..second-child (controller)
..second-child (pre-link)
..second-child (post-link)
parent (post-link)

Здесь мы можем заметить, что загрузка вложенных директив начинается после функции preLink родительской директивы и ее функция postLink вызовется только после полного цикла загрузки всех дочерних директив.

Основные фазы

На предыдущем примере отчетливо видны две основные фазы загрузки директивы: фаза компиляции (compile phase) и фаза связывания или линковки (link phase). Давайте рассмотрим их подробнее.

Компиляция

После загрузки HTML разметки браузером, AngularJS вызывает свою функцию $compile, которая также проходит по разметке сверху вниз и вызывает функцию compile у всех обнаруженных директив. Результатом выполнения этой функции является функция link, которая будет вызвана в фазе связывания.

Следующий график отображает этот процесс:

Связывание

На этой фазе AngularJS сперва вызывает функцию controller, которая создаст контроллер директивы. Далее вызовется функция preLink, затем будут обработаны директивы, найденные в дочерних элементах, и после этого вызывается функция postLink.

Если элементы html добавляются динамически, например, с помощью директивы ng-repeat, то они также пройдут все фазы компиляции и связывания.

График фазы линковки:

Полный график фазы компиляции и связывания

На данном графике можно увидеть в какой момент происходит удаление исходного содержимого элемента директивы (Transcluded content removed), и сохранено в памяти для будущей вставки в шаблон директивы или для доступа в controller.

Также отображено, на каком этапе директива получает html шаблон и в какой момент AngularJS создает область видимости (scope and isolate scope) для директивы.

Использование функций

Далее, мы рассмотрим отдельно основные функции объекта определения директивы, и определим для каких целей какая лучше подходит, и что реализовывать не рекомендуется.

Функция компиляции

Это место для выполнения (исходных) манипуляций с шаблонами, которые еще не связаны с областью видимостью или привязкой данных.

Рекомендуется:

Не рекомендуется:

Функция контроллера

Основное назначение функции контроллера:

Не рекомендуется:

Функция Pre-link

Функция pre-link используется редко, но может быть полезна в специальных сценариях.

Например, когда дочерний контроллер регистрирует себя с родительским контроллером.

Сразу после вызова этой функции начнётся фаза связывания для дочерних элементов, для которых текущая область видимости будет служить родительской.

Не рекомендуется:

Функция Post-link

Когда вызывается функция post-link, все предыдущие шаги завершились - подготовка шаблона, привязка данных и т. д. Если директива не содержит бизнес логики и не требует предварительной обработки шаблона, вы можете сразу использовать функцию объекта определения директивы link. В сокращенной записи она и будет являться функцией post-link.

Рекомендуется:

Сравнительная таблица функций директивы

Для удобства вынесем все рекомендации по использованию функций директивы в отдельную таблицу.

Заключение

Четкое знание жизненного цикла директив AngularJS позволит разрабатывать более сложные компоненты приложения, реализовывать красивые инженерные решения сложных задач и предотвратит возникновение распространенных ошибок.

Всем удачи и процветания!

, , , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *