Різниця між функціями "контролер", "посилання" та "компілювати" при визначенні директиви


393

Деякі місця, здається, використовують функцію контролера для логіки директиви, а інші використовують посилання. У прикладі вкладок на домашній сторінці кутових використовується контролер для однієї та посилання для іншої директиви. Яка різниця між ними?


Відповіді:


635

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

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

  • функція зв'язку - зазвичай використовується для реєстрації зворотних викликів слухачів (тобто $watchвиразів на області), а також оновлення DOM (тобто, маніпулювання iElement = окремий елемент екземпляра). Він виконується після клонування шаблону. Наприклад, всередині <li ng-repeat...>, функція зв’язку виконується після того, як <li>шаблон (tElement) був клонований (в iElement) для цього конкретного <li>елемента. A $watchдозволяє директиві повідомляти про зміни властивостей діапазону (область застосування пов'язана з кожним екземпляром), що дозволяє директиві надавати оновлене значення екземпляра DOM.

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

    Щоб отримати більш поглиблене пояснення директив вкладок і панелей, а також чому директива вкладок створює функцію на своєму контролері за допомогою this(а не на $scope), дивіться "this" vs $ range в контролерах AngularJS .

Як правило, ви можете розмістити методи $watchesтощо в контролер директиви або у функцію зв'язку. Контролер запуститься першим, що іноді має значення (див. Цю скрипку, яка реєструється, коли функції ctrl та link запускаються з двома вкладеними директивами). Як згадував Джош у коментарі , ви можете покласти функції маніпулювання сферою всередині контролера лише для узгодження з рештою фреймворку.


131
Це пояснення має бути в основних документах AngularJS або хоча б посилання на нього
Dogoku

7
Це інформативна відповідь, але я думаю, що це важко читати. Можливо, можуть допомогти більше пунктуації та менші речення. Загалом я вдячний за відповідь.
Марті Кортес

$ Компілятор ігнорує атрибут 'link' за наявності атрибута 'compile'. А як щодо наявності атрибута "контролер"? Чи викликає "контролер" компілятор $ ігнорування атрибутів "link" та "compile" або обидва? Чи можливо та / або доцільно використовувати "компілювати" разом із "контролером"?
Карл Г

1
@CarlG, наявність атрибута контролера не впливає на компілятор $ стосовно зв'язку та компіляції. Можна використовувати компілятор і контролер.
Марк Райкок

1
"DOM слухачів" НЕ "(тобто, $ watch вирази в області застосування)". Один слухає DOM для подібних подій mouseover, інший - для зміни властивостей. Велика різниця.
Дмитро Зайцев

56

Як доповнення до відповіді Марка, функція компіляції не має доступу до області застосування, але функція посилання робить.

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


3
+1 для посилання на відео. Це дуже інформативно.
Роб Кільті


35
  1. запущений код перед компіляцією: використовуйте контролер
  2. запущений код після компіляції: використовуйте Посилання

Кутова умова: запишіть ділову логіку в контролер і DOM маніпулювання посиланням.

Крім цього, ви можете викликати одну функцію контролера з функції зв’язку іншої директиви. Наприклад, у вас є 3 власні директиви

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

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

http://egghead.io/lessons/angularjs-directive-зв'язок буде корисним дізнатися про міждирективні комунікації


18
"запущений код перед компіляцією: використовувати контролер". Це неправильно; compileзавжди буде виконуватися раніше controller .
Іжакі

Ви не зможете (принаймні не прямолінійно) отримати доступ до тварин із вашої директиви про леопарда. Дочірні директиви можуть отримати доступ до методів контролера в батьківській директиві, але директиви щодо братів та братів (як у прикладі вище) не можуть викликати контролери один одного.
Бенджамін Вайт

2
Чи справді леопарди є типом пантери? Крім того, на стороні примітки ... Чи можете ви мати посилання - AND - контролер в директиві?
Коді

1
так, леопард / ягуари - це пантери. і так, у вас є посилання та контролер в межах директиви.
Рахуль

1
З посібника для розробників Angular: "Найкраща практика: використовуйте контролер, коли ви хочете відкрити API іншим директивам. В іншому випадку використовуйте посилання."
Мартін ван Дріель

6

функція компіляції -

  1. викликається перед функцією контролера та зв'язку.
  2. У функції компіляції у вас є оригінальний шаблон DOM, щоб ви могли вносити зміни до оригінального DOM до того, як AngularJS створить його примірник і перед тим, як буде створено область застосування
  3. ng-repe є ідеальним прикладом - оригінальний синтаксис - це шаблон шаблону, повторювані елементи в HTML - це екземпляри
  4. Може бути декілька примірників елементів і лише один елемент шаблону
  5. Область застосування ще не доступна
  6. Функція компіляції може повернути функцію та об'єкт
  7. повернення функції (пост-посилання) - еквівалентно реєстрації функції зв’язку через властивість зв'язку об’єкта конфігурації, коли функція компіляції порожня.
  8. повернення об'єкта з функціями (іми), зареєстрованими за допомогою властивостей до та після - дозволяє контролювати, коли функцію зв’язування слід викликати під час фази зв’язування. Інформацію про функції попереднього зв’язування та після зв’язування див. Нижче.

синтаксис

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

контролер

  1. викликається після функції компіляції
  2. тут доступний обсяг
  3. можна отримати доступ до інших директив (див. атрибут вимагати)

попереднє посилання

  1. Функція посилання відповідає за реєстрацію слухачів DOM, а також за оновлення DOM. Він виконується після клонування шаблону. Саме тут буде вкладена більшість логіки директиви.

  2. Можна оновити dom в контролері за допомогою angular.element, але це не рекомендується, оскільки елемент передбачений у функції посилання

  3. Функція попереднього посилання використовується для реалізації логіки, яка запускається, коли угловий js вже компілював дочірні елементи, але перед тим, як було викликано будь-яке дочірнє поштове посилання

пост-посилання

  1. Директива, яка має лише функцію посилання, angular розглядає функцію як посилання

  2. повідомлення буде виконуватися після компіляції, контролера та функції попереднього посилання, тому саме це вважається найбезпечнішим і за замовчуванням місцем для додавання вашої логіки директиви

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.