Связь между вложенными директивами

61

Кажется, существует довольно много способов связи между директивами. Скажем, у вас есть вложенные директивы, где внутренние директивы должны сообщать что-то внешнему (например, это было выбрано пользователем).

<outer>
  <inner></inner>
  <inner></inner>
</outer>

Пока у меня есть 5 способов сделать это

require: родительская директива

innerДиректива может потребовать outerдирективу, которая может подвергнуть какой - либо метод на своем контроллере. Так что в innerопределении

require: '^outer',
link: function(scope, iElement, iAttrs, outerController) {
   // This can be passed to ng-click in the template
   $scope.chosen = function() {
     outerController.chosen(something);
   }
}

И в outerконтроллере директивы:

controller: function($scope) {
   this.chosen = function(something) {
   }
}

$emit мероприятие

innerДиректива может $emitсобытие, которого outerдиректива может реагировать, через $on. Итак, в innerконтроллере директивы:

controller: function($scope) {
  $scope.chosen = function() {
    $scope.$emit('inner::chosen', something);
  }
}

и в outerдирективах контроллера:

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>

Таким образом, innerконтроллер имеет функцию «innerChoose», которую он может вызвать

scope: {
  'innerChoose': '&'
},
controller: function() {
  $scope.click = function() {
    $scope.innerChoose({item:something});
  }
}

который будет вызывать (в данном случае) функцию 'functionOnOuter' в области действия outerдирективы:

controller: function($scope) {
  $scope.functionOnOuter = function(item) {
  }
}

Наследование области на неизолированной области

Учитывая, что это вложенные контроллеры, наследование области может работать, и внутренняя директива может просто вызывать любые функции в цепочке областей действия, если только она не имеет изолированной области видимости). Итак, в innerдирективе:

// scope: anything but a hash {}
controller: function() {
  $scope.click = function() {
    $scope.functionOnOuter(something);
  }
}

И в outerдирективе:

controller: function($scope) {
  $scope.functionOnOuter = function(item) {
  }
}

Службой впрыскивается как во внутренний, так и во внешний

Служба может быть введена в обе директивы, поэтому они могут иметь прямой доступ к одному и тому же объекту или вызывать функции для уведомления службы и, возможно, даже зарегистрировать себя для уведомления в пабе / подсистеме. Это не требует, чтобы директивы были вложенными.

Вопрос : Каковы потенциальные недостатки и преимущества каждого из них перед другими?

Михал Чарамза
источник
5
Я не могу поверить, что я не видел этот вопрос до сих пор. Я ценю все варианты, которые вы предоставили. Если вы еще этого не сделали, подумали ли вы опубликовать этот вопрос на stackoverflow? Я ожидал бы, что это получит намного больше тяги на стеке потока.
Майк Барлоу - BarDev
Пожалуйста, смотрите это предложение - softwareengineering.stackexchange.com/questions/344165/…
yellowblood

Ответы:

7

Я предпочитаю определять &атрибут в области действия директивы прежде всего потому, что я рассматриваю scope: {}определение директивы как ее API. Гораздо проще взглянуть на определение атрибута области видимости, чтобы увидеть, какую информацию требуется директиве для правильного функционирования, чем для поиска ссылок и функций контроллера для $emitсобытий d, унаследованных функций области действия или функций, используемых внутри введенных контроллеров.

Джефф Свенсен
источник
1

Мое мнение:

Службы являются предпочтительным способом обмена поведением / данными между модулями / директивами / контроллерами. Директивы - это изолированные вещи, которые могут быть вложенными или нет. Контроллеры должны как можно больше придерживаться модели представления, в идеале бизнес-логика не должна быть там.

Так:

Когда вы начнете связывать их вместе с помощью доступа к родительским функциям области действия, я думаю, что вы рискуете связать их слишком сложно и сделать все приложение нечитаемым, а компоненты - повторно. Когда вы разделяете эти общие данные или поведение в службе, вы получаете преимущество повторного использования целых директив с различными данными / поведением, даже определяя службу, которая будет использоваться во время выполнения. Вот что такое инъекция зависимостей.

RobbyD
источник