Связь с компилятором и контроллером
Когда вы создаете директиву, вы можете поместить код в компилятор, функцию связи или контроллер.
В документах они объясняют, что:
- Функция компиляции и связывания используется в разных фазах angular
цикл
- контроллеры разделяются между директивами
Однако для меня неясно, какой код должен идти туда.
Например: могу ли я создавать функции в компиляции и привязывать их к области действия в ссылке или только прикреплять функции к области в контроллере?
Как контроллеры распределяются между директивами, если каждая директива может иметь свой собственный контроллер? Являются ли контроллеры действительно разделяемыми или это просто свойства области?
Ответы
Ответ 1
Скомпилировать:
Это фаза, где Angular фактически компилирует вашу директиву. Эта функция компиляции вызывается только один раз для каждой ссылки на данную директиву. Например, предположим, что вы используете директиву ng-repeat. ng-repeat придется искать элемент, к которому он присоединен, извлечь фрагмент html, к которому он присоединен, и создать функцию шаблона.
Если вы использовали HandleBars, шаблоны underscore или их эквивалент, то, как и компиляция их шаблонов для извлечения функции шаблона. К этой функции шаблона вы передаете данные, а возвращаемое значение этой функции - html с данными в правильных местах.
Фаза компиляции - это шаг в Angular, который возвращает функцию шаблона. Эта функция шаблона в Angular называется функцией связывания.
Фаза связывания:
Эта фаза связывания - это привязка данных ($ scope) к функции связывания, и она должна вернуть вам связанный html. Так как директива также указывает, куда идет этот html или что он меняет, это уже хорошо. Это функция, в которой вы хотите внести изменения в связанный html, т.е. Html, который уже имеет прикрепленные к нему данные. В Angular, если вы пишете код в функции связывания, его обычно выполняет функция пост-ссылки (по умолчанию). Это своего рода обратный вызов, который вызывается после того, как функция связывания связала данные с шаблоном.
Контроллер:
Контроллер - это место, где вы вводите определенную логику определенной директивы. Эта логика также может войти в функцию связывания, но тогда вам придется поместить эту логику в область действия, чтобы сделать ее "доступной". Проблема в том, что тогда вы будете развращать область с вашими директивами, что на самом деле не является чем-то, что ожидается.
Итак, какова альтернатива, если две Директивы хотят поговорить друг с другом/сотрудничать друг с другом? Конечно, вы можете поместить всю эту логику в сервис, а затем заставить обе эти директивы зависеть от этой службы, но это просто приводит к еще одной зависимости. Альтернативой является предоставление контроллера для этой области (обычно изолировать область?), А затем этот контроллер вводится в другую директиву, когда эта директива "требует" другой. См. Вкладки и панели на первой странице angularjs.org для примера.
Ответ 2
Я хотел добавить и то, что говорит команда O'Reily AngularJS от команды Google:
Контроллер. Создайте контроллер, который публикует API для связи по всем директивам. Хорошим примером является Директива по установлению связи.
Ссылка - программно модифицировать результирующие экземпляры элементов DOM, добавлять прослушиватели событий и настраивать привязку данных.
Компиляция. Программно модифицируйте шаблон DOM для функций в копиях директивы, как при использовании в ng-repeat. Функция компиляции также может возвращать функции ссылок для изменения результирующих экземпляров элемента.
Ответ 3
A directive
позволяет расширять словарь HTML декларативным способом для создания веб-компонентов. Атрибут ng-app
является директивой, поэтому ng-controller
и все ng- prefixed attributes
. Директивы могут быть attributes
, tags
или даже class
names
, comments
.
Как рождаются директивы (compilation
и instantiation
)
Скомпилировать: Хорошо использовать функцию compile
как для manipulate
DOM перед ее визуализацией, так и вернуть функцию link
(которая будет обрабатывать ссылку для нас). Это также место для размещения любых методов, которые необходимо обменивать со всеми instances
этой директивой.
ссылка: Хорошо использовать функцию link
для регистрации всех слушателей на определенном элементе DOM (который клонируется из шаблона) и настроить наши привязки к странице.
Если установлено в функции compile()
, они были бы установлены только один раз (что часто бывает так, как вы хотите). Если они установлены в функции link()
, они будут устанавливаться каждый раз, когда элемент HTML привязан к данным в объекте
.
<div ng-repeat="i in [0,1,2]">
<simple>
<div>Inner content</div>
</simple>
</div>
app.directive("simple", function(){
return {
restrict: "EA",
transclude:true,
template:"<div>{{label}}<div ng-transclude></div></div>",
compile: function(element, attributes){
return {
pre: function(scope, element, attributes, controller, transcludeFn){
},
post: function(scope, element, attributes, controller, transcludeFn){
}
}
},
controller: function($scope){
}
};
});
Функция compile
возвращает функцию ссылки pre
и post
. В функции предварительной ссылки у нас есть шаблон экземпляра, а также область действия из controller
, но тем не менее шаблон не связан с областью действия и до сих пор не имеет транксированного содержимого.
post
Функция ссылки - это когда post link является последней выполняемой функцией. Теперь transclusion
завершен, the template is linked to a scope
и view will update with data bound values after the next digest cycle
. Опция link
- это просто ярлык для настройки функции post-link
.
:. Контроллер директивы может быть передан на другую фазу связывания/компиляции. Он может быть введен в другие руководства как средство для использования в межстраничной коммуникации.
Необходимо указать имя требуемой директивы - оно должно быть привязано к одному элементу или его родительскому элементу. Имя может иметь префикс:
? – Will not raise any error if a mentioned directive does not exist.
^ – Will look for the directive on parent elements, if not available on the same element.
Используйте квадратную скобку [‘directive1′, ‘directive2′, ‘directive3′]
, чтобы потребовать несколько контроллеров директив.
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope, $element) {
});
app.directive('parentDirective', function() {
return {
restrict: 'E',
template: '<child-directive></child-directive>',
controller: function($scope, $element){
this.variable = "Hi Vinothbabu"
}
}
});
app.directive('childDirective', function() {
return {
restrict: 'E',
template: '<h1>I am child</h1>',
replace: true,
require: '^parentDirective',
link: function($scope, $element, attr, parentDirectCtrl){
//you now have access to parentDirectCtrl.variable
}
}
});
Ответ 4
Кроме того, хорошая причина использовать функцию контроллера или ссылки (поскольку у них есть доступ к области, элементу и attr), это потому, что вы можете передавать любой доступный сервис или зависимость в контроллер (и в любом порядке), тогда как вы не можете сделать это со ссылкой. Обратите внимание на разные подписи:
controller: function($scope, $exceptionHandler, $attr, $element, $parse, $myOtherService, someCrazyDependency) {...
против.
link: function(scope, element, attrs) {... //no services allowed
Ответ 5
это хороший образец для понимания фаз директивы
http://codepen.io/anon/pen/oXMdBQ?editors=101
var app = angular.module('myapp', [])
app.directive('slngStylePrelink', function() {
return {
scope: {
drctvName: '@'
},
controller: function($scope) {
console.log('controller for ', $scope.drctvName);
},
compile: function(element, attr) {
console.log("compile for ", attr.name)
return {
post: function($scope, element, attr) {
console.log('post link for ', attr.name)
},
pre: function($scope, element, attr) {
$scope.element = element;
console.log('pre link for ', attr.name)
// from angular.js 1.4.1
function ngStyleWatchAction(newStyles, oldStyles) {
if (oldStyles && (newStyles !== oldStyles)) {
forEach(oldStyles, function(val, style) {
element.css(style, '');
});
}
if (newStyles) element.css(newStyles);
}
$scope.$watch(attr.slngStylePrelink, ngStyleWatchAction, true);
// Run immediately, because the watcher first run is async
ngStyleWatchAction($scope.$eval(attr.slngStylePrelink));
}
};
}
};
});
HTML
<body ng-app="myapp">
<div slng-style-prelink="{height:'500px'}" drctv-name='parent' style="border:1px solid" name="parent">
<div slng-style-prelink="{height:'50%'}" drctv-name='child' style="border:1px solid red" name='child'>
</div>
</div>
</body>
Ответ 6
- compile: используется, когда нам нужно изменить шаблон директивы, например добавить новое выражение, добавить другую директиву внутри этой директивы
- контроллер: используется, когда нам нужно разделить/повторно использовать данные области $
- ссылка: это функция, которая используется, когда нам нужно присоединить обработчик событий или манипулировать DOM.