Angular JS: У чому полягає потреба функції зв'язку директиви, коли у нас вже був контролер директиви зі сферою застосування?


199

Мені потрібно виконати деякі операції над сферою та шаблоном. Здається, я можу це зробити і в linkфункції, або у controllerфункції (оскільки обидва мають доступ до області).

Коли це так, коли мені потрібно використовувати linkфункцію, а не контролер?

angular.module('myApp').directive('abc', function($timeout) {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        scope: true,
        link: function(scope, elem, attr) { /* link function */ },
        controller: function($scope, $element) { /* controller function */ }
    };
}

Також я розумію, що linkце некутовий світ. Таким чином, я можу використовувати $watch, $digestі $apply.

Яке значення linkфункції, коли у нас вже був контролер?


9
Що ви маєте в виду « Крім того , я розумію , що посилання є не кутовий світ. Таким чином, я можу використовувати $watch, $digestі $apply. »?
musically_ut

2
Всередині linkми не бачимо жодної кутової магії. тобто немає двосторонніх прив’язок і т. д. Просто те, що у нас є доступні для використання кутові api.
Yugal Jindle

Відповіді:


299

Після моєї початкової боротьби з linkі controllerфункціями і читання досить багато про них, я думаю , що тепер у мене є відповідь.

Спочатку давайте зрозуміти ,

Як у двох словах працюють кутові директиви:

  • Ми починаємо з шаблону (як рядок або завантажений у рядок)

    var templateString = '<div my-directive>{{5 + 10}}</div>';

  • Тепер це templateStringобгорнуто як кутовий елемент

    var el = angular.element(templateString);

  • З el, тепер ми збираємо його , $compileщоб отримати назад посилання функцію.

    var l = $compile(el)

    Ось що відбувається,

    • $compile переглядає весь шаблон і збирає всі директиви, які він розпізнає.
    • Усі виявлені директиви складаються рекурсивно і linkзбираються їх функції.
    • Потім всі linkфункції загортаються в нову linkфункцію і повертаються як l.
  • Нарешті, ми надаємо scopeфункцію цій l(посилальній) функції, яка надалі виконує функції загорнутого посилання з цим scopeта відповідними їм елементами.

    l(scope)

  • Це додає templateяк новий вузол до DOMі викликає, controllerякий додає його годинник до області, якою поділяється з шаблоном у DOM.

введіть тут опис зображення

Порівняння компіляції проти лінії проти контролера :

  • Кожна директива складається лише один раз і функція зв'язку зберігається для повторного використання. Тому, якщо є щось застосовне до всіх примірників директиви, слід виконувати всередині compileфункції директиви .

  • Тепер після компіляції у нас є linkфункція, яка виконується під час прикріплення шаблону до DOM . Отже, ми виконуємо все, що є специфічним для кожного примірника директиви. Наприклад: прикріплення подій , вимкнення шаблону на основі обсягу тощо.

  • Нарешті, призначено, що контролер буде доступний для живого та активного реагування, поки директива працює на DOM(після додавання). Тому:

    (1) Після налаштування виду [ V ] (тобто шаблону) із посиланням. $scopeє нашим [ M ] і $controllerє нашим [ C ] в MVC

    (2) Скористайтеся двостороннім прив’язкою до $ range , встановивши годинник.

    (3) $scopeочікується, що годинники будуть додані в контролер, оскільки саме це переглядає шаблон під час виконання.

    (4) Нарешті, controllerтакож використовується для спілкування між відповідними директивами. (Як, myTabsнаприклад, https://docs.angularjs.org/guide/directive )

    (5) Це правда, що ми могли все це зробити і в цій linkфункції, але це стосується розділення проблем .

Тому, нарешті, ми маємо наступне, що ідеально відповідає всім творам:

введіть тут опис зображення


5
Я також вважав цю статтю корисною для розуміння порядку виконання тут:
Ніт-гріст

4
Чудове пояснення. Хотілося б зазначити, що контролер викликається перед функцією зв'язку.
jsbisht

38
контролер виконується перед посиланням
Royi Namir

10
Мене гніває те, що Stack Overflow вимагає, щоб зміни були принаймні 6 символів, таким чином, не дозволяючи мені виправити написання даної відповіді.
користувач1886323

79

Для чого потрібні контролери

Різниця між linkі controllerвступає в дію, коли ви хочете вкладати директиви у своєму DOM та виставляти функції API від батьківської директиви до вкладених.

З документів :

Найкраща практика: використовуйте контролер, коли ви хочете розкрити API іншими директивами. В іншому випадку використовуйте посилання.

Скажіть, ви хочете мати дві директиви, my-formі my-text-inputви хочете, щоб my-text-inputдиректива з'являлася тільки всередині my-formі ніде більше.

У цьому випадку, ви будете говорити при визначенні директиви , my-text-inputщо вона вимагає контролера від parentелемента DOM з використанням вимагає аргументу, наприклад: require: '^myForm'. Тепер контролер від батьківського елемента буде injectedв linkфункцію в якості четвертого аргументу, наступний $scope, element, attributes. Ви можете викликати функції цього контролера та спілкуватися з батьківською директивою.

Більше того, якщо такого контролера не буде знайдено, з’явиться помилка.

Навіщо взагалі використовувати посилання

Немає реальної необхідності використовувати цю linkфункцію, якщо вона визначає, controllerоскільки $scopeце є на controller. Більше того, визначаючи і те, linkі інше controller, потрібно бути обережним щодо порядку виклику обох ( controllerвиконується раніше).

Однак, у відповідності з кутовим способом , більшість маніпуляцій з DOM та використання двостороннього зв’язування $watchersзазвичай виконується у linkфункції, тоді як API для дітей та $scopeманіпуляції виконуються в controller. Це не важке і швидке правило, але це зробить код більш модульним і допоможе розділити проблеми (контролер буде підтримувати directiveстан, а linkфункція підтримуватиме DOM+ зовнішні прив’язки).


Це чудово. Тепер, чи можете ви мені допомогти з другою частиною питання?
Yugal Jindle

Я маю на увазі, оскільки у нас існував контролер, який міг використовуватися для зв'язку з іншими директивами. Отже, у чому була потреба link?
Yugal Jindle

1
Ваша відповідь якось не відповідає на власне питання.
Yugal Jindle

1
Чи є проблеми, які виникають, коли ми визначаємо controller? Чому я хочу винайти зовсім нову функцію, щоб уникнути визначення контролера?
Yugal Jindle

1
здається, що @scalaGirl s Link більше не працює
Minato

17

controllerФункція / об'єкт являє собою абстракцію модель-уявлення-контролер (MVC). Хоча нічого не можна писати про MVC, це все-таки є найважливішим перевагою кутового: розділити питання на більш дрібні шматки. І це все, нічого більше, тому якщо вам потрібно реагувати на Modelзміни, що виникають з Viewбоку, Controller- це правильна людина, яка виконує цю роботу.

Історія про linkфункцію різна, вона йде з іншого погляду, ніж MVC. І це дуже важливо, як тільки ми хочемо перетнути межі controller/model/view (шаблону) .

Почнемо з початку параметри, передані у linkфункцію:

function link(scope, element, attrs) {
  • Об'єм - це кутовий об'єкт.
  • елемент - обернутий jqLite елемент, який відповідає цій директиві.
  • attrs - об’єкт з нормалізованими іменами атрибутів та відповідними їм значеннями.

Щоб поставити це linkв контекст, слід зазначити, що всі директиви проходять цей етап процесу ініціалізації: « Компілювати» , « Посилання» . Виписка з книги Бреда Гріна та Шиям Сешадрі Angular JS :

Фаза компіляції (сестра посилання, згадаймо її тут, щоб отримати чітке уявлення):

У цій фазі Angular йде по DOM, щоб визначити всі зареєстровані директиви в шаблоні. Потім для кожної директиви вона перетворює DOM на основі правил директиви (шаблон, заміна, трансклудація тощо) та викликає функцію компіляції, якщо вона існує. Результатом є компільована функція шаблону,

Фаза зв'язку :

Щоб зробити перегляд динамічним, Angular потім виконує функцію посилання для кожної директиви. Функції зв'язку зазвичай створюють слухачів у DOM або моделі. Ці слухачі постійно підтримують перегляд та модель синхронізуються.

Гарний приклад того, як користуватися, linkможна знайти тут: Створення користувацьких директив . Дивіться приклад: Створення директиви, яка маніпулює DOM , яка вставляє "дата-час" на сторінку, оновлюється щосекунди.

Лише дуже короткий фрагмент із цього багатого джерела, який показує справжню маніпуляцію з DOM. Існує підключена функція до $ timeout-сервісу, а також вона очищається в її виклику деструктора, щоб уникнути витоку пам'яті

.directive('myCurrentTime', function($timeout, dateFilter) {

 function link(scope, element, attrs) {

 ...

 // the not MVC job must be done
 function updateTime() {
   element.text(dateFilter(new Date(), format)); // here we are manipulating the DOM
 }

 function scheduleUpdate() {
   // save the timeoutId for canceling
   timeoutId = $timeout(function() {
     updateTime(); // update DOM
     scheduleUpdate(); // schedule the next update
   }, 1000);
 }

 element.on('$destroy', function() {
   $timeout.cancel(timeoutId);
 });

 ...

3
Ви, здається, порівняли compilerі link. Вони задаються питанням, чому linkколи у нас вже булоcontroller
Югал Джіндл

Я розширив відповідь, щоб більш детально описати навіть контролер. Тепер концепції controllervs linkповинні бути більш чіткими ...
Радім Келер

1
Я можу шукати, щоб погодитися з цим поясненням. Але це, здається, там ніби розмито. Було б чудово, якщо хтось із вуглової команди сам може виступити за це, спроектувавши, куди вони бачать, що це йде - до того linkчи іншого controller.
Yugal Jindle

1
Це єдина частина, яку я хочу зрозуміти (Коли цього недостатньо?). Плюс, я отримую всі переваги кутового controllerі linkє відносно некрасивим. Отже, кутова команда повинна мати для цього вагомі причини, а не просто варіант.
Yugal Jindle

1
Питання: Коли контролера недостатньо? Відповідь: Якщо вам потрібен досвід з кутом, наприклад, для використання плагіна JQuery або використання функції JQlite, як зазначено в документі ( docs.angularjs.org/api/ng/function/angular.element:) , тоді вам знадобиться посилання
Hasteq
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.