3

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

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 行。)

http://plnkr.co/edit/AXUVX9zdJx1tApDhgH32

这是我的首要目标:我为第二个指令使用隔离范围的原因是将内部范围与外部范围分开。(在我的项目中使用的实际“第二个指令”比这个玩具示例复杂得多。这就是必要的原因。)我知道 AngularJS 提供了将外部范围映射到指令的内部范围的机制。我很好奇这些机制中的任何一个对于映射基于事件的通信的事件是否有用。

如果答案是隔离范围对于基于事件的通信是不可逾越的,那么在我已经说明的情况下,完成指令到指令通信的最佳方法是什么,同时仍然实现我的目标?谢谢!

4

1 回答 1

5

这来自两个问题。

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

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

2)第二个问题是您的第二个指令在隔离时不会按原样处理范围嵌入,因此在 DOM 中更深定义的 HTML 将不会共享该指令隔离范围,但上面的那个没有定义data.

将隔离范围传播到内部 HTML 的方法是在link函数中使用以下代码段:

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

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

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

于 2015-05-07T23:18:42.233 回答