Лучший способ общения между директивами
Скопировано отсюда. Может быть, я могу получить более правильный ответ здесь!
Кажется, существует довольно много способов связи между директивами. Скажем, у вас есть вложенные директивы, где внутренние директивы должны сообщать что-то внешнему (например, это было выбрано пользователем).
<outer>
<inner></inner>
<inner></inner>
</outer>
Пока у меня есть 5 способов сделать это
требуют: родительская директива
Внутренняя директива может требовать внешней директивы, которая может предоставлять некоторый метод в своем контроллере. Так что во внутреннем определении
require: '^outer',
link: function(scope, iElement, iAttrs, outerController) {
// This can be passed to ng-click in the template
$scope.chosen = function() {
outerController.chosen(something);
}
}
И в контроллере внешней директивы:
controller: function($scope) {
this.chosen = function(something) {
}
}
событие $emit
Внутренняя директива может $emit событие, на которое внешняя директива может ответить, через $on. Итак, в контроллере внутренней директивы:
controller: function($scope) {
$scope.chosen = function() {
$scope.$emit('inner::chosen', something);
}
}
а во внешнем директиве контроллера:
controller: function($scope) {
$scope.$on('inner::chosen, function(e, data) {
}
}
Выполнить выражение в родительской области через &
Элемент может привязаться к выражению в родительской области и выполнить его в соответствующую точку. HTML будет выглядеть так:
<outer>
<inner inner-choose="functionOnOuter(item)"></inner>
<inner inner-choose="functionOnOuter(item)"></inner>
</outer>
Таким образом, внутренний контроллер имеет функцию innerChoose, которую он может вызвать
scope: {
'innerChoose': '&'
},
controller: function() {
$scope.click = function() {
$scope.innerChoose({item:something});
}
}
который будет вызывать (в данном случае) функцию ' functionOnOuter' в области видимости внешней директивы:
controller: function($scope) {
$scope.functionOnOuter = function(item) {
}
}
Наследование области на неизолированной области
Учитывая, что это вложенные контроллеры, наследование области может работать, и внутренняя директива может просто вызывать любые функции в цепочке областей действия, если она не имеет изолированной области видимости). Итак, во внутренней директиве:
// scope: anything but a hash {}
controller: function() {
$scope.click = function() {
$scope.functionOnOuter(something);
}
}
И во внешней директиве:
controller: function($scope) {
$scope.functionOnOuter = function(item) {
}
}
Службой впрыскивается как во внутренний, так и во внешний
Служба может быть внедрена в обе директивы, поэтому они могут иметь прямой доступ к одному и тому же объекту или вызывать функции для уведомления службы и, возможно, даже зарегистрировать себя для уведомления в пабе / подсистеме. Это не требует, чтобы директивы были вложенными.
Вопрос: Каковы потенциальные недостатки и преимущества каждого из них перед другими?
2 ответа
Во-первых, я хочу отметить, что ваш пример
<Наружный>inner> inner> Наружная>
не будет работать с
объем: { 'innerChoose': '&' }, контроллер: функция () { $scope.click = function() { $ Scope.innerChoose({пункт: что-то}); } }
Вам нужно либо запустить все выражение innerChoose с помощью $parse, либо вам нужно только передать ссылку на функцию, например:
<Наружный>inner> inner> Наружная>
Помимо этого, все сводится к тому, что имеет смысл в зависимости от стилистических предпочтений вашей команды и того, что вам конкретно необходимо выполнить. Например, если вам нужно иметь возможность выполнять команды, настроенные на основе данных в JSON, которые неизвестны заранее, на основе нескольких слоев, которые могут быть объединены различными способами, вам, вероятно, нужно идти с событиями, потому что любая связь вообще может помешать вам создать или выполнить правильную команду на правильных данных.
Если основной задачей, которую вам нужно сделать, является создание представлений, использующих эту функциональность, вы можете использовать общую область $, чтобы представления были как можно более простыми.
Я в основном просто использую require для ngModel, который является скорее директивой родного брата, чем директивой parent. У меня еще не было варианта использования для ссылки на весь родительский контроллер.
Когда у нас есть такая иерархия, я бы выбрал первый вариант. require
был создан для соединения двух директив или компонентов (из Angular 1.5). Вы можете использовать это, чтобы указать, что вы просто не можете использовать inner
без outer
,
Я не фанат событий, потому что они могут пройти через много областей, когда мы неправильно используем.
Настройки & и scope имеют некоторые преимущества, но это зависит от того, что вы хотите. Это не применимо для всех случаев.
Я думаю, что в настоящее время в таких дискуссиях мы должны принимать во внимание Angular 2. Там, если вы хотите выполнить функцию из дочернего компонента, вам нужно передать этот компонент с аннотацией @ViewChild. Я думаю, что наиболее близким решением в Angular 1.x является использование require, которое (как я уже говорил) также реализовано для компонентов Angular 1.x.