通过隔离作用域的 AngularJS 基于事件的通信 [英] AngularJS event-based communication through isolate scope

查看:20
本文介绍了通过隔离作用域的 AngularJS 基于事件的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 AngularJS 中,一个指令如何使用基于事件的通信($emit$broadcast$on)与另一个指令进行通信具有隔离范围的指令?我创建了两个指令,当从第二个指令中删除隔离作用域时,第一个指令能够使用发射成功地与第二个进行通信.但是,当将隔离作用域重新添加到第二个作用域时,通信就会中断.

In AngularJS, how can one directive use event-based communication ($emit, $broadcast and $on) to communicate with another directive which has an isolate scope? I've created two directives, and when the isolate scope is removed from the second directive, the first directive is able to use emit to successfully communicate with the second. However, when the isolate scope is added back to the second, communication breaks down.

var app = angular.module('myApp', []);

app.directive("firstDir", function() {
  return {
    restrict: 'E',
    controller: function($scope) {
      $scope.set = function() {
        $scope.$emit('MY_NEW_SEARCH', $scope.searchQuery);
      }       
    },
    template: '<input type="text" ng-model="searchQuery"><button ng-click="set()">Change Value</button>'
  };  
});

app.directive("secondDir", function() {
  return {
    restrict : 'E',
    scope: {},
    controller : function($scope) {    
      var _that = $scope;
      $scope.$on('MY_NEW_SEARCH', function(e, data) {
        _that.data = data;
      });
      $scope.data = 'init value';   
    }
  };  
});

我创建了一个 Plunker 来说明这个问题.您会注意到,如果您注释掉第二个指令的指令定义对象中的范围"属性,则通信有效:您可以在第一个指令的输入框中键入一个字符串,然后按下第一个指令的按钮指令,并将字符串传送到第二个指令,后者将其显示在视图上.(就目前而言,Plunker 已损坏,因为隔离范围问题,请参阅 app.js 文件的第 19 行.)

I've created a Plunker to illustrate the issue. You'll notice that if you comment out the "scope" property in the directive definition object of the second directive, communication works: You're able to type a string into the input box of the first directive, press the button of the first directive, and the string is communicated to the second directive, which displays it on the view. (As it stands, the Plunker is broken, because of the isolate scope issue, see line 19 of the app.js file.)

http://plnkr.co/edit/AXUVX9zdJx1tApDhgH32

这是我的总体目标:我为第二个指令使用隔离作用域的原因是将内部作用域与外部作用域分开.(在我的项目中使用的实际第二条指令"比这个玩具示例复杂得多.这就是它的必要性.)我知道 AngularJS 提供了将外部作用域映射到指令内部作用域的机制.我很好奇这些机制是否对映射基于事件的通信的事件有用.

Here's my overarching goal: The reason I'm using an isolate scope for the second directive is to separate the scope inside from the scope outside. (The actual "second directive" used in my project is much more complex than this toy example. That's what makes this necessary.) I know AngularJS provides mechanisms for the mapping of the outer scope to a directive's inner scope. I'm curious if any of these mechanisms are useful for mapping the events of event-based communication.

如果答案是基于事件的通信无法克服隔离范围,那么在我所说明的情况下完成指令到指令通信的最佳方法是什么,同时仍能实现我的目标?谢谢!

If the answer turns out to be that an isolate scope is insurmountable for event-based communication, what's the best way to accomplish directive to directive communication in the case which I've illustrated, while still accomplishing my goals? Thank you!

推荐答案

这来自两个问题.

1) 第一个是因为两个指令在 HTML 中处于同一级别,您不能 $emit 从一个范围到另一个范围的事件(除非它们具有相同的范围,就是这种情况当第二个指令没有独立的作用域时).

1) This first one is since both directives are on the same level in HTML, you cannot $emit an event from one scope to another (unless they have the same scope, which is the case when the second directive doesn't have an isolated scope).

为了让第一个指令与第二个指令联系,您可以用 $scope.$root.$broadcast 替换 $scope.$emit(在范围层次结构中向上)(从根作用域向下延伸到其所有子作用域),或者在您的情况下只是 $scope.$broadcast 因为第一个指令作用域实际上是根作用域!

In order for the first directive to contact the second, you can replace $scope.$emit (which goes upward in the scopes hierarchy) by $scope.$root.$broadcast (which goes downward from the root scope to all its children), or simply $scope.$broadcast in your case as this first directive scope is in fact the root scope!

2) 第二个问题是你的第二个指令,当被隔离时,不会按原样处理范围嵌入,所以在 DOM 中更深层次定义的 HTML 不会共享该指令隔离的范围,但上面的那个不t 定义data.

2) The second problem is that your second directive, when isolated, doesn't handle scope transclusion as is, so the HTML defined deeper in the DOM will not share that directive isolated scope, but the one above, which doesn't define data.

将隔离作用域传播到内部 HTML 的方法是在 link 函数中使用此代码段:

The way to propagate an isolated scope to the inner HTML is by using this snippet within the link function:

link: function(scope, element, attrs, ctrl, transclude) {
  transclude(scope, function(clone) {
    element.append(clone);
  });
}

这是一个有两个修复程序的工作 Plnker:

here is a working Plnker with both fixes:

http://plnkr.co/edit/I9Vmutal2gfqyLIU0iAe?p=preview

这篇关于通过隔离作用域的 AngularJS 基于事件的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆