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

358

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

Теги:
web-applications
javascript-framework

5 ответов

589

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

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

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

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

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

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

  • 131
    Это объяснение должно быть в основных документах AngularJS или, по крайней мере, ссылаться на него.
  • 5
    +1 хорошо сказано, мистер Райкок.
Показать ещё 8 комментариев
54

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

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

  • 3
    +1 за ссылку на видео. Это очень информативно.
  • 2
    jvandemo.com/...
35
  • текущий код перед компиляцией: используйте контроллер
  • текущий код после компиляции: используйте Ссылка

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

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

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

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

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

  • 17
    msgstr "запуск кода перед компиляцией: используйте контроллер". Это неверно; compile всегда будет выполняться до controller .
  • 0
    Вы не сможете (по крайней мере, не простым способом) получить доступ к животному из директивы вашего леопарда. Дочерние директивы могут обращаться к методам контроллера в родительской директиве, но дочерние директивы (как в примере выше) не могут вызывать контроллеры друг друга.
Показать ещё 4 комментария
5

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

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

синтаксис

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

контроллер

  • вызывается после функции компиляции Область
  • доступна здесь.
  • могут быть доступны другими директивами (см. атрибут require)

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

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

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

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

пост-связь

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

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

-7

Добавление о контроллере:

Подпись contoller (из документации):

 controller: function($scope, $element, $attrs, $transclude, otherInjectables) { 
    ... 
 },

Последний, думаю, важен. Поскольку вы можете вводить переменные типа $location, $anchorScroll и т.д. В директиву с помощью контроллера. Как я знаю, они недоступны со ссылкой.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню