协慌网

登录 贡献 社区

使用 $ scope。$ emit 和 $ scope。$ on

如何使用.$emit.$on方法将$scope对象从一个控制器发送到另一个控制器?

function firstCtrl($scope) {
    $scope.$emit('someEvent', [1,2,3]);
}

function secondCtrl($scope) {
    $scope.$on('someEvent', function(mass) { console.log(mass); });
}

它不像我认为的那样工作。 $emit$on work 如何运作?

答案

首先,父子范围关系确实很重要。你有两种可能发出一些事件:

  • $broadcast - 将事件向下发送到所有子范围,
  • $emit - 通过范围层次结构向上调度事件。

我对控制器(范围)关系一无所知,但有几种选择:

  1. 如果范围firstCtrl是母公司secondCtrl范围,你的代码应该通过更换工作$emit$broadcastfirstCtrl

    function firstCtrl($scope)
    {
        $scope.$broadcast('someEvent', [1,2,3]);
    }
    
    function secondCtrl($scope)
    {
        $scope.$on('someEvent', function(event, mass) { console.log(mass); });
    }
  2. 如果您的范围之间没有父子关系,您可以将$rootScope注入控制器并将事件广播到所有子范围(即secondCtrl )。

    function firstCtrl($rootScope)
    {
        $rootScope.$broadcast('someEvent', [1,2,3]);
    }
  3. 最后,当您需要将子控制器中的事件调度到范围向上时,您可以使用$scope.$emit 。如果firstCtrl范围是firstCtrl范围的父secondCtrl

    function firstCtrl($scope)
    {
        $scope.$on('someEvent', function(event, data) { console.log(data); });
    }
    
    function secondCtrl($scope)
    {
        $scope.$emit('someEvent', [1,2,3]);
    }

我还建议第四个选项作为 @zbynour 提议选项的更好替代方案。

无论传输和接收控制器之间的关系如何,都使用$rootScope.$emit而不是$rootScope.$broadcast 。这样,事件保持在$rootScope.$$listeners的集合中,而使用$rootScope.$broadcast ,事件传播到所有子范围,其中大多数可能不是该事件的监听器。当然,在接收控制器的最后,你只需使用$rootScope.$on

对于此选项,您必须记住销毁控制器的 rootScope 侦听器:

var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
$scope.$on('$destroy', function () {
  unbindEventHandler();
});

如何使用。$ emit 和。$ on 方法将 $ scope 对象从一个控制器发送到另一个控制器?

您可以在应用层次结构中发送所需的任何对象,包括$ scope

这是关于广播发射如何工作的快速概念。

注意下面的节点; 全部嵌套在节点 3 中。当您拥有此场景时,您将使用广播发出

注意:此示例中每个节点的数量是任意的; 它很容易成为头号人物; 二号; 甚至是 1,348 号。每个数字只是此示例的标识符。这个例子的重点是显示 Angular 控制器 / 指令的嵌套。

3
           ------------
           |          |
         -----     ------
         1   |     2    |
      ---   ---   ---  ---
      | |   | |   | |  | |

看看这棵树。你如何回答以下问题?

注:还有其他的方法来回答这些问题,但在这里我们将讨论广播散发 。此外,当阅读下面的文本时,假设每个数字都有自己的文件(指令,控制器)ex one.js,two.js,three.js。

如何节点1发言,节点3?

在文件one.js 中

scope.$emit('messageOne', someValue(s));

在文件three.js 中 - 所有子节点的最高节点需要进行通信。

scope.$on('messageOne', someValue(s));

节点 2 如何与节点 3 对话?

在文件two.js 中

scope.$emit('messageTwo', someValue(s));

在文件three.js 中 - 所有子节点的最高节点需要进行通信。

scope.$on('messageTwo', someValue(s));

节点 3 如何与节点 1 和 / 或节点 2 通话?

在文件three.js 中 - 所有子节点的最高节点需要进行通信。

scope.$broadcast('messageThree', someValue(s));

在文件one.js && two.js 中您要捕获消息的文件或两者。

scope.$on('messageThree', someValue(s));

节点 2 如何与节点 1 通信?

在文件two.js 中

scope.$emit('messageTwo', someValue(s));

在文件three.js 中 - 所有子节点的最高节点需要进行通信。

scope.$on('messageTwo', function( event, data ){
  scope.$broadcast( 'messageTwo', data );
});

在文件one.js 中

scope.$on('messageTwo', someValue(s));

然而

当你让所有这些嵌套的子节点试图像这样进行通信时,你会很快看到许多$ on$ broadcast$ emit

这就是我喜欢做的事情。

在最高的 PARENT NODE(在这种情况下为3 ......),这可能是你的父控制器......

所以,在文件three.js 中

scope.$on('pushChangesToAllNodes', function( event, message ){
  scope.$broadcast( message.name, message.data );
});

现在,在任何子节点中,您只需要$ $ 发出消息或使用$ on捕获它。

注意:通常很容易在一个嵌套路径中进行串扰,而不使用$ emit$ broadcast$ on ,这意味着大多数用例都是在您尝试让节点1与节点2进行通信时,反之亦然。

节点 2 如何与节点 1 通信?

在文件two.js 中

scope.$emit('pushChangesToAllNodes', sendNewChanges());

function sendNewChanges(){ // for some event.
  return { name: 'talkToOne', data: [1,2,3] };
}

在文件three.js 中 - 所有子节点的最高节点需要进行通信。

我们已经处理过这个了吗?

在文件one.js 中

scope.$on('talkToOne', function( event, arrayOfNumbers ){
  arrayOfNumbers.forEach(function(number){
    console.log(number);
  });
});

您仍然需要对要捕获的每个特定值使用$ on ,但现在您可以在任何节点中创建任何您喜欢的内容,而不必担心如何在我们捕获和广播时跨父节点间隙获取消息通用pushChangesToAllNodes

希望这可以帮助...