Мне нужно выполнить некоторые операции с областью действия и шаблоном. Кажется, что я могу сделать это либо в функции 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
- это мир не angular. Поэтому я могу использовать $watch
, $digest
и $apply
.
Каково значение функции link
, когда у нас уже был контроллер?
Ответ 1
После моей начальной борьбы с функциями link
и controller
и чтения о них много, я думаю, теперь у меня есть ответ.
Сначала позволяет понимать,
Как директивы angular работают в двух словах:
-
Начнем с шаблона (в виде строки или загруженного в строку)
var templateString = '<div my-directive>{{5 + 10}}</div>';
-
Теперь этот templateString
завернут как элемент angular
var el = angular.element(templateString);
-
С el
теперь мы скомпилируем его с помощью $compile
, чтобы вернуть функцию link.
var l = $compile(el)
Вот что происходит,
-
$compile
просматривает весь шаблон и собирает все директивы, которые он распознает.
- Все обнаруженные директивы скомпилированы рекурсивно, и их функции
link
собраны.
- Затем все функции
link
завертываются в новую функцию link
и возвращаются как l
.
-
Наконец, мы предоставляем функцию scope
этой функции l
(link), которая дополнительно выполняет связанные функции привязки с этим scope
и их соответствующими элементами.
l(scope)
-
Это добавляет template
в качестве нового node к DOM
и вызывает controller
, который добавляет свои часы в область , которая совместно используется с шаблоном в DOM.
![enter image description here]()
Сравнение компилирования vs link vs контроллера:
-
Каждая директива скомпилирована только один раз, а функция ссылка сохраняется для повторного использования. Поэтому, если в директиве compile
должно выполняться что-то, применимое ко всем экземплярам директивы.
-
Теперь после компиляции мы имеем функцию link
, которая выполняется при прикреплении шаблона к DOM. Поэтому мы выполняем все, что характерно для каждого экземпляра директивы. Например: прикрепление событий, , изменение шаблона на основе области и т.д.
-
Наконец, контроллер должен быть доступен как живым, так и реактивным, в то время как директива работает на DOM
(после присоединения). Поэтому:
(1) После настройки представления [ V] (т.е. шаблона) со ссылкой. $scope
является нашей [ M], а $controller
является нашей [ C] в M V C
(2) Воспользуйтесь привязкой 2-way с $scope, настроив часы.
(3) $scope
ожидается, что часы будут добавлены в контроллер, так как это то, что наблюдает за шаблоном во время выполнения.
(4) Наконец, controller
также используется для связи между связанными директивами. (Пример myTabs
в https://docs.angularjs.org/guide/directive)
(5) Это правда, что мы могли бы сделать все это в функции link
, а также о разделении проблем.
Поэтому, наконец, мы имеем следующее, которое идеально подходит ко всем частям:
![enter image description here]()
Ответ 2
Для чего нужны контроллеры
Разница между link
и controller
вступает в игру, когда вы хотите вставлять директивы в DOM и выставлять функции API из родительской директивы в вложенные.
Из docs:
Best Practice: используйте контроллер, если вы хотите открыть API для других директив. В противном случае используйте ссылку.
Предположим, что у вас есть две директивы my-form
и my-text-input
, и вы хотите, чтобы директива my-text-input
отображалась только внутри my-form
и нигде больше.
В этом случае вы укажете при определении директивы my-text-input
, что для этого требуется контроллер из элемента parent
DOM с помощью аргумента require
, вот так: require: '^myForm'
. Теперь контроллер из родительского элемента будет injected
в функцию link
в качестве четвертого аргумента, следуя за $scope, element, attributes
. Вы можете вызывать функции на этом контроллере и взаимодействовать с родительской директивой.
Кроме того, если такой контроллер не найден, ошибка будет повышена.
Зачем использовать ссылку вообще
Нет реальной необходимости использовать функцию link
, если она определяет controller
, поскольку $scope
доступен на controller
. Кроме того, определяя как link
, так и controller
, нужно быть осторожным относительно порядка вызова двух (controller
выполняется раньше).
Однако, в соответствии с методом Angular, большинство манипуляций с DOM и двухсторонняя привязка с использованием $watchers
обычно выполняются в функции link
, тогда как API для детей и $scope
выполняется в controller
. Это не сложное и быстрое правило, но при этом код будет более модульным и поможет в разделении проблем (контроллер будет поддерживать состояние directive
, а функция link
будет поддерживать внешние привязки DOM
+).
Ответ 3
Функция/t controller
представляет собой абстракцию модели-представления-контроллера (MVC). Хотя о MVC нет ничего нового, он по-прежнему является самым значительным преимуществом angular: разделить проблемы на более мелкие части. И что это, не более того, поэтому, если вам нужно реагировать на Model
изменения, исходящие от View
, controller
является правильным человеком для выполнения этой работы.
История о функции link
различна, она исходит с другой точки зрения, а затем с MVC. И действительно важно, как только мы хотим пересечь границы controller/model/view
(шаблон).
Давайте начнем с параметров, которые передаются в функцию link
:
function link(scope, element, attrs) {
- область - объект области Angular.
Элемент
- - это элемент, обернутый jqLite, который соответствует этой директиве.
- attrs - это объект с нормализованными именами атрибутов и их соответствующими значениями.
Чтобы помещать link
в контекст, следует упомянуть, что все директивы проходят эти шаги процесса инициализации: Compile, Link. Извлечение из книги Брэда Грина и Шьяма Сешадри Angular JS:
Скомпилировать фазу (сестра ссылки, давайте укажем здесь, чтобы получить четкое изображение):
В этой фазе Angular проходит DOM, чтобы идентифицировать все зарегистрированные
директивы в шаблоне. Для каждой директивы она преобразует
DOM на основе правил директив (шаблон, замена, переключение и
и так далее) и вызывает функцию компиляции, если она существует. Результатом является
скомпилированная функция шаблона,
Фаза связи:
Чтобы сделать динамический вид, Angular затем запускает функцию ссылки для каждого директивы. Функции ссылок обычно создают слушатели на DOM или модели. Эти слушатели сохраняют представление и модель в синхронизации на все время.
Хороший пример использования link
можно найти здесь: Создание пользовательских директив. См. Пример: Создание директивы, которая манипулирует DOM, которая вставляет "дату-время" на страницу, обновляемую каждую секунду.
Просто очень короткий фрагмент из этого богатого источника выше, показывая реальные манипуляции с DOM. Функция $hookout подключена к функции $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);
});
...
Ответ 4
Я добавлю еще один момент к существующим ответам. Функция привязки гарантированно будет подключена после того, как DOM будет готов, поэтому это может быть связано с использованием ссылки.