简体   繁体   English

指令之间通信的最佳方式

[英]Best way for communication between directives

Copied from here . 这里复制。 May be, I can get more proper answer here! 可能是,我可以在这里得到更正确的答案!

There seem to be quite a few ways of communicating between directives. 似乎有很多方法在指令之间进行通信。 Say you have nested directives, where the inner directives must communicate something to the outer (eg it's been chosen by the user). 假设您有嵌套指令,其中内部指令必须与外部通信(例如,它已被用户选择)。

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

So far I have 5 ways of doing this 到目前为止,我有5种方法可以做到这一点

require: parent directive require:父指令

The inner directive can require the outer directive, which can expose some method on its controller. 内部指令可以要求外部指令,它可以在其控制器上公开某些方法。 So in the inner definition 所以在内在的定义

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

And in the outer directive's controller: 在外部指令的控制器中:

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

$emit event $ emit事件

The inner directive can $emit an event, which the outer directive can respond to, via $on. 内部指令可以$ $发出一个事件,外部指令可以通过$ on响应。 So in the inner directive's controller: 所以在内部指令的控制器中:

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

and in the outer directives controller: 并在外部指令控制器中:

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

Execute expression in parent scope, via & 在父作用域中执行表达式,通过&

The item can bind to an expression in the parent scope, and execute it at an appropriate point. 该项可以绑定到父作用域中的表达式,并在适当的位置执行它。 The HTML would be like: HTML就像:

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

So the inner controller has an 'innerChoose' function it can call 所以内部控制器有一个可以调用的“innerChoose”函数

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

which would call (in this case) the 'functionOnOuter' function on the outer directive's scope: 这将调用(在这种情况下)外部指令范围内的'functionOnOuter'函数:

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

Scope inheritance on non-isolated scope 范围继承非隔离范围

Given that these are nested controllers, scope inheritance can be at work, and the inner directive can just call any functions in the scope chain, as long as it doesn't have an isolated scope). 鉴于这些是嵌套控制器,范围继承可以起作​​用,而内部指令只能调用范围链中的任何函数,只要它没有隔离的范围)。 So in the inner directive: 所以在内部指令中:

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

And in the outer directive: 并在外部指令:

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

By service injected into both inner and outer 通过注入内部和外部的服务

A service can be injected into both directives, so they can have direct access to the same object, or call functions to notify the service, and maybe even register themselves to be notified, in a pub/sub system. 服务可以注入到两个指令中,因此它们可以直接访问同一个对象,或者调用函数来通知服务,甚至可以在pub / sub系统中注册自己以获得通知。 This doesn't require the directives to be nested. 这不需要嵌套指令。

Question: What are any potential drawbacks and advantages of each over the others? 问题:每个人有什么潜在的缺点和优势?

First, I want to point out that your example 首先,我想指出你的例子

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

is not going to work with 是不会合作的

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

You either need to run the entire innerChoose expression with $parse, or you need to only pass a reference to the function, like: 您需要使用$ parse运行整个innerChoose表达式,或者您只需要传递对该函数的引用,例如:

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

Beyond that, it comes down to what makes best sense based on the stylistic preferences of your team and what you specifically need to accomplish. 除此之外,它还归结为基于团队的风格偏好以及您需要完成的内容最有意义的内容。 For example, if you need to be able to execute commands that are set up based on data in JSON that's not known in advance based on multiple layers that can be put together in different ways, you probably need to go with events, because any coupling at all could prevent you from creating or executing the right command on the right data. 例如,如果您需要能够执行基于JSON中的数据而设置的命令,这些数据基于可以以不同方式组合在一起的多个层而事先不知道,那么您可能需要使用事件,因为任何耦合完全可以阻止您在正确的数据上创建或执行正确的命令。

If the main task that you need to do is build Views that leverage the functionality, you might want to go with a shared $scope to keep the Views as simple as possible. 如果您需要执行的主要任务是构建利用该功能的视图,您可能希望使用共享的$ scope来保持视图尽可能简单。

I mainly just use require for ngModel, which is more of a sibling directive than parent directive. 我主要只使用require for ngModel,它更像兄弟指令而不是父指令。 I haven't yet had a use-case for needing a reference to the entire parent controller. 我还没有用于需要引用整个父控制器的用例。

When we have a hierarchy like this, I would go with the first option. 当我们有这样的层次结构时,我会选择第一个选项。 require was created to couple two directives or components (from Angular 1.5) tightly. 创建require以紧密耦合两个指令或组件(来自Angular 1.5)。 You can use this to point out that you just cannot use inner without outer . 你可以用它来指出你不能在没有outer情况下使用inner

I'm not a fan of events, because they can go through many scopes when we have a wrong usage. 我不是事件的粉丝,因为当我们使用错误时,他们可以经历许多范围。

& and scope settings have some advantages, but it depends on what you want. &和范围设置有一些优点,但这取决于你想要什么。 Those are not applicable for all cases. 这些并不适用于所有情况。

I think nowadays in such discussions we should take Angular 2 into account. 我认为现在在这样的讨论中我们应该考虑Angular 2。 There if you want to execute a function from child component, you need to pass this component with @ViewChild annotation. 如果要从子组件执行函数,则需要使用@ViewChild批注传递此组件。 I think the closest solution in Angular 1.x is to use require, which (as I've mentioned) is also implemented for Angular 1.x components. 我认为Angular 1.x中最接近的解决方案是使用require,它(如我所提到的)也是为Angular 1.x组件实现的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM