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

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

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

这不是我想的那样。$emit和$on如何工作?


当前回答

为了将$scope对象从一个控制器发送到另一个控制器,我将讨论$rootScope。$broadcast和$rootScope。$emit是最常用的。

案例1:

$rootScope.$broadcast:-

$rootScope.$broadcast('myEvent',$scope.data);//Here `myEvent` is event name

$rootScope.$on('myEvent', function(event, data) {} //listener on `myEvent` event

$rootScope监听器不会自动销毁。你需要使用$destroy来销毁它。最好使用$scope。$scope上的监听器$on被自动销毁,即一旦$scope被销毁。

$scope.$on('myEvent', function(event, data) {}

Or,

  var customeEventListener = $rootScope.$on('myEvent', function(event, data) {

  }
  $scope.$on('$destroy', function() {
        customeEventListener();
  });

案例2:

rootScope。美元发出:

   $rootScope.$emit('myEvent',$scope.data);

   $rootScope.$on('myEvent', function(event, data) {}//$scope.$on not works

$emit和$broadcast的主要区别是$rootScope。$emit事件必须使用$rootScope监听。$on,因为触发的事件从来没有向下通过作用域树。 在这种情况下,您还必须像使用$broadcast一样销毁侦听器。

编辑:

我不喜欢使用$rootScope。$broadcast + $scope。$on但使用 rootScope美元。发出+ rootScope。美元美元。rootScope美元。美元广播+ 美元的范围。$on组合可能会导致严重的性能问题。这是 因为事件会在所有范围内扩散。

编辑2:

在这个回答中提到的问题已经在angular.js中解决了 1.2.7。编写版本$broadcast现在避免冒泡未注册的作用域 运行速度和$emit一样快。

其他回答

下面的代码显示了两个子控制器,事件从它们向上分派到父控制器(rootScope)

<body ng-app="App">

    <div ng-controller="parentCtrl">

        <p>City : {{city}} </p>
        <p> Address : {{address}} </p>

        <div ng-controller="subCtrlOne">
            <input type="text" ng-model="city" />
            <button ng-click="getCity(city)">City !!!</button>
        </div>

        <div ng-controller="subCtrlTwo">

            <input type="text" ng-model="address" />
            <button ng-click="getAddrress(address)">Address !!!</button>

        </div>

    </div>

</body>

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

// parent controller
App.controller('parentCtrl', parentCtrl);

parentCtrl.$inject = ["$scope"];

function parentCtrl($scope) {

    $scope.$on('cityBoom', function(events, data) {
        $scope.city = data;
    });

    $scope.$on('addrBoom', function(events, data) {
        $scope.address = data;
    });
}

// sub controller one

App.controller('subCtrlOne', subCtrlOne);

subCtrlOne.$inject = ['$scope'];

function subCtrlOne($scope) {

    $scope.getCity = function(city) {

        $scope.$emit('cityBoom', city);    
    }
}

// sub controller two

App.controller('subCtrlTwo', subCtrlTwo);

subCtrlTwo.$inject = ["$scope"];

function subCtrlTwo($scope) {

    $scope.getAddrress = function(addr) {

        $scope.$emit('addrBoom', addr);   
    }
}

http://jsfiddle.net/shushanthp/zp6v0rut/

<!DOCTYPE html>
<html>

<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
var app = angular.module('MyApp',[]);
app.controller('parentCtrl',function($scope){
  $scope.$on('MyEvent',function(event,data){    
    $scope.myData = data;
  });
 });

app.controller('childCtrl',function($scope){
  $scope.fireEvent = function(){ 
  $scope.$emit('MyEvent','Any Data');
  }  
 });
</script>
</head>
<body ng-app="MyApp">
<div ng-controller="parentCtrl" ng-model="myName">

{{myData}}

 <div ng-controller="childCtrl">
   <button ng-click="fireEvent()">Fire Event</button>
 </div>

</div>
</body>
</html>

这是我的函数:

$rootScope.$emit('setTitle', newVal.full_name);

$rootScope.$on('setTitle', function(event, title) {
    if (scope.item) 
        scope.item.name = title;
    else 
        scope.item = {name: title};
});

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

使用rootScope美元。$emit而不是$rootScope。不管发送和接收控制器之间的关系。这样,事件就保留在$rootScope的集合中。$$监听器,而$rootScope。将事件传播到所有子作用域,其中大多数子作用域可能不是该事件的监听器。当然,在接收控制器端,你只需使用$rootScope。$on。

对于这个选项,你必须记得销毁控制器的rootScope监听器:

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

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

你可以在应用的层次结构中发送任何你想要的对象,包括$scope。

下面简要介绍一下广播和发射的工作原理。

注意下面的节点;都嵌套在节点3中。在这种情况下使用broadcast和emit。

注意:本例中每个节点的编号是任意的;它很容易成为第一;数字2;甚至是1348。对于这个例子,每个数字只是一个标识符。这个例子的重点是展示Angular控制器/指令的嵌套。

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

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

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

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

在文件1。js中

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

在文件3 .js中——所有需要通信的子节点的最上面的节点。

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

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

在文件two.js中

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

在文件3 .js中——所有需要通信的子节点的最上面的节点。

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

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

在文件3 .js中——所有需要通信的子节点的最上面的节点。

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

在文件one.js && two.js中,你想要捕获消息的文件或两者都有。

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

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

在文件two.js中

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

在文件3 .js中——所有需要通信的子节点的最上面的节点。

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

在文件1。js中

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

然而

当所有这些嵌套的子节点试图像这样通信时,您将很快看到许多$on、$broadcast和$emit。

这是我喜欢做的事情。

在最上面的父节点中(在本例中是3…),这可能是你的父控制器…

在文件3。js中

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

现在,在任何子节点中,您只需要$emit消息或使用$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] };
}

在文件3 .js中——所有需要通信的子节点的最上面的节点。

我们已经处理过了,记得吗?

在文件1。js中

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

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