Разница между функциями 'controller', 'link' и 'compile' при определении директивы

393

Некоторые места, кажется, используют функцию контроллера для логики директив, а другие используют ссылку. Пример вкладок на угловой домашней странице использует контроллер для одной и ссылку для другой директивы. Какая разница между двумя?

user1558259
источник

Ответы:

635

Я собираюсь немного расширить ваш вопрос, а также включить функцию компиляции.

  • функция компиляции - используется для манипулирования DOM шаблона (т. е. манипуляции с элементом tElement = template), следовательно, манипуляции, которые применяются ко всем клонам DOM шаблона, связанным с директивой. (Если вам также нужна функция ссылки (или функции ссылки до и после), и вы определили функцию компиляции, функция компиляции должна возвращать функцию (и) ссылки, потому что 'link'атрибут игнорируется, если 'compile'атрибут определен.)

  • Функция Link - обычно используется для регистрации обратных вызовов слушателя (т. е. $watchвыражений в области), а также для обновления DOM (т. е. манипуляции с iElement = индивидуальный элемент экземпляра). Это выполняется после того, как шаблон был клонирован. Например, внутри <li ng-repeat...>функции link выполняется после того, как <li>шаблон (tElement) был клонирован (в iElement) для этого конкретного <li>элемента. A $watchпозволяет директиве получать уведомления об изменениях свойства области (область действия связана с каждым экземпляром), что позволяет директиве отображать обновленное значение экземпляра в DOM.

  • функция контроллера - должна использоваться, когда другая директива должна взаимодействовать с этой директивой. Например, на домашней странице AngularJS директива pane должна добавить себя в область, поддерживаемую директивой tabs, следовательно, директива tabs должна определить метод контроллера (думаю, API), к которому директива pane может обращаться / вызывать.

    Для более подробного объяснения директив tabs и pane, и почему директива tabs создает функцию на своем контроллере, используя this(а не on $scope), пожалуйста, смотрите «this» против $ scope в контроллерах AngularJS .

В общем случае вы можете помещать методы $watchesи т. Д. Либо в контроллер директивы, либо в функцию link. Сначала будет запущен контроллер, что иногда имеет значение (см. Эту скрипку, которая регистрирует, когда функции ctrl и link запускаются с двумя вложенными директивами). Как упоминал Джош в комментарии , вы можете захотеть поместить функции манипулирования областью в контроллер просто для согласованности с остальной частью фреймворка.

Марк Райкок
источник
131
Это объяснение должно быть в основных документах AngularJS или хотя бы на него есть ссылка
Dogoku
7
Это информативный ответ, но я думаю, что это трудно читать. Возможно, больше пунктуации и небольших предложений могут помочь. В целом я благодарен за ответ.
Марти Кортес,
$ Compiler игнорирует атрибут 'link' при наличии атрибута 'compile'. Но как насчет наличия атрибута «контроллер»? Приводит ли 'controller' $ compiler к игнорированию одного или обоих атрибутов 'link' и 'compile'? Возможно ли и / или целесообразно использовать «компиляцию» вместе с «контроллером»?
Карл Дж.
1
@CarlG, наличие атрибута controller не влияет на $ compiler в отношении ссылки и компиляции. Вы можете использовать компиляцию и контроллер.
Марк Райкок
1
«Слушатели DOM» НЕ являются «(т. Е. Выражениями $ watch в области видимости)». Один слушает DOM для подобных событий mouseover, другой слушает область изменения свойств. Большая разница.
Дмитрий Зайцев
56

В дополнение к ответу Марка, функция компиляции не имеет доступа к области видимости, но функция ссылки имеет.

Я действительно рекомендую это видео; Написание директив Миско Хевери (отец AngularJS), где он описывает различия и некоторые приемы. (Разница между функцией компиляции и функцией ссылки на отметке 14:41 на видео ).

Pixic
источник
3
+1 за ссылку на видео. Это очень информативно.
Роб Келти,
2
jvandemo.com/…
EMuentes,
35
  1. запуск кода перед компиляцией: используйте контроллер
  2. запуск кода после компиляции: используйте ссылку

Угловое соглашение: написать бизнес-логику в контроллере и манипулирование DOM в ссылке.

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

<animal>
<panther>
<leopard></leopard>
</panther> 
</animal>

и вы хотите получить доступ к животным изнутри директивы "леопард".

http://egghead.io/lessons/angularjs-directive-communication будет полезно узнать о межправительственной связи

Рахул
источник
18
msgstr "запуск кода перед компиляцией: используйте контроллер". Это неверно; compileвсегда будет выполняться раньше controller .
Изаки
Вы не сможете (по крайней мере, не простым способом) получить доступ к животному из директивы леопарда. Дочерние директивы могут обращаться к методам контроллера в родительской директиве, но дочерние директивы (как в примере выше) не могут вызывать контроллеры друг друга.
Бенджамин Уайт
2
Действительно ли леопарды - пантера? Кроме того, на заметку ... Можете ли вы иметь ссылку - И - контроллер в директиве?
Коди
1
да леопард / ягуары это пантеры. и да, у вас есть ссылка и контроллер в директиве.
Рахул
1
Из руководства разработчика Angular: «Лучшая практика: используйте контроллер, если вы хотите представить API другим директивам. В противном случае используйте ссылку».
Мартин ван Дриэль
6

функция компиляции -

  1. вызывается перед контроллером и функцией связи.
  2. В функции компиляции у вас есть оригинальный шаблон DOM, поэтому вы можете вносить изменения в исходный DOM до того, как AngularJS создаст его экземпляр, и до того, как будет создана область действия.
  3. ng-repeat - отличный пример - оригинальный синтаксис является элементом шаблона, повторяющиеся элементы в HTML являются экземплярами
  4. Может быть несколько экземпляров элемента и только один элемент шаблона.
  5. Область еще не доступна
  6. Функция компиляции может возвращать функцию и объект
  7. возвращение функции (post-link) - эквивалентно регистрации функции связывания через свойство link объекта config, когда функция компиляции пуста.
  8. Возврат объекта с функцией (ями), зарегистрированной через свойства pre и post - позволяет вам контролировать, когда должна вызываться функция связывания во время фазы связывания. См. Информацию о функциях предварительной ссылки и последующей ссылки ниже.

синтаксис

function compile(tElement, tAttrs, transclude) { ... }

контроллер

  1. вызывается после функции компиляции
  2. объем доступен здесь
  3. могут быть доступны с помощью других директив (см. атрибут require)

предварительная ссылка

  1. Функция ссылки отвечает за регистрацию слушателей DOM, а также за обновление DOM. Это выполняется после того, как шаблон был клонирован. Именно здесь будет помещена большая часть директивной логики.

  2. Вы можете обновить dom в контроллере, используя angular.element, но это не рекомендуется, так как элемент предоставляется в функции link

  3. Функция предварительной ссылки используется для реализации логики, которая запускается, когда angular js уже скомпилировал дочерние элементы, но до того, как какая-либо ссылка на запись дочернего элемента была вызвана

пост-ссылка

  1. директива, которая имеет только функцию ссылки, angular рассматривает функцию как ссылку для публикации

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

Сунил Гарг
источник