指令之间通信的最佳方式

时间:2016-05-31 15:13:34

标签: javascript angularjs design-patterns angularjs-directive angularjs-events

here复制。可能是,我可以在这里得到更恰当的答案!

指令之间似乎有很多种沟通方式。假设您有嵌套指令,其中内部指令必须与外部通信(例如,用户已选择它)。

<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 event

内部指令可以$ $发出一个事件,外部指令可以通过$ on响应。所以在内部指令的控制器中:

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

并在外部指令控制器中:

controller: function($scope) {
  $scope.$on('inner::chosen, function(e, data) {
  }
}

通过&amp;

在父作用域中执行表达式

该项可以绑定到父作用域中的表达式,并在适当的位置执行它。 HTML就像:

<outer>
  <inner inner-choose="functionOnOuter(item)"></inner>
  <inner inner-choose="functionOnOuter(item)"></inner>
</outer>

所以内部控制器有一个&#39; innerChoose&#39;它可以调用的功能

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

会调用(在这种情况下)&#39; functionOnOuter&#39;函数在外部指令的范围内:

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) {
  }
}

通过注入内部和外部的服务

服务可以注入到两个指令中,因此它们可以直接访问同一个对象,或者调用函数来通知服务,甚至可以在pub / sub系统中注册自己以获得通知。这并不要求指令嵌套。

问题:每个人的潜在缺点和优势是什么?

2 个答案:

答案 0 :(得分:2)

首先,我想指出你的例子

<outer>
  <inner inner-choose="functionOnOuter(item)"></inner>
  <inner inner-choose="functionOnOuter(item)"></inner>
</outer>

无法使用

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

您需要使用$ parse运行整个innerChoose表达式,或者只需要传递对该函数的引用,例如:

<outer>
  <inner inner-choose="functionOnOuter"></inner>
  <inner inner-choose="functionOnOuter"></inner>
</outer>

除此之外,它归结为基于团队的风格偏好以及您特别需要完成的内容,以最佳方式。例如,如果您需要能够执行基于JSON中的数据而设置的命令,这些数据基于可以以不同方式组合在一起的多个层而事先不知道,那么您可能需要使用事件,因为任何耦合完全可以阻止你在正确的数据上创建或执行正确的命令。

如果您需要做的主要任务是构建利用该功能的视图,您可能希望使用共享的$ scope来保持视图尽可能简单。

我主要只使用require for ngModel,它更像兄弟指令而不是父指令。我还没有需要引用整个父控制器的用例。

答案 1 :(得分:1)

当我们有这样的层次结构时,我会选择第一个选项。创建require以紧密耦合两个指令或组件(来自Angular 1.5)。您可以使用它指出,如果没有inner,则无法使用outer

我不是事件的粉丝,因为当我们使用错误时,他们可以通过很多范围。

&安培;和范围设置有一些优点,但这取决于你想要什么。这些并不适用于所有情况。

我认为现在在这样的讨论中我们应该考虑Angular 2。如果要从子组件执行函数,则需要使用@ViewChild批注传递此组件。我认为Angular 1.x中最接近的解决方案是使用require,其中(我已经提到过)也是为Angular 1.x组件实现的。