Trabajando con $scope.$emit y $scope.$on

Resuelto Paul Kononenko asked hace 11 años • 0 respuestas

¿ Cómo puedo enviar mi $scopeobjeto de un controlador a otro usando métodos .$emity ?.$on

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

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

No funciona como creo que debería. ¿Cómo funcionan $emity $onfuncionan?

Paul Kononenko avatar Jan 24 '13 20:01 Paul Kononenko
Aceptado

En primer lugar, la relación entre el ámbito padre-hijo sí importa. Tienes dos posibilidades para emitir algún evento:

  • $broadcast-- envía el evento hacia abajo a todos los ámbitos secundarios,
  • $emit-- envía el evento hacia arriba a través de la jerarquía de alcance.

No sé nada sobre la relación de sus controladores (ámbitos), pero hay varias opciones:

  1. Si el alcance de firstCtrles padre del secondCtrlalcance, su código debería funcionar reemplazando $emitpor $broadcasten firstCtrl:

    function firstCtrl($scope)
    {
        $scope.$broadcast('someEvent', [1,2,3]);
    }
    
    function secondCtrl($scope)
    {
        $scope.$on('someEvent', function(event, mass) { console.log(mass); });
    }
    
  2. En caso de que no exista una relación padre-hijo entre sus ámbitos, puede inyectar $rootScopeen el controlador y transmitir el evento a todos los ámbitos secundarios (es decir, también secondCtrl).

    function firstCtrl($rootScope)
    {
        $rootScope.$broadcast('someEvent', [1,2,3]);
    }
    
  3. Finalmente, cuando necesite enviar el evento desde el controlador secundario a ámbitos superiores, puede usar $scope.$emit. Si el alcance de firstCtrles padre del secondCtrlalcance:

    function firstCtrl($scope)
    {
        $scope.$on('someEvent', function(event, data) { console.log(data); });
    }
    
    function secondCtrl($scope)
    {
        $scope.$emit('someEvent', [1,2,3]);
    }
    
zbynour avatar Jan 24 '2013 13:01 zbynour

Además, sugeriría una cuarta opción como una mejor alternativa a las opciones propuestas por @zbynour.

Utilice $rootScope.$emiten lugar de $rootScope.$broadcastindependientemente de la relación entre el controlador transmisor y receptor. De esa manera, el evento permanece dentro del conjunto $rootScope.$$listenersmientras que $rootScope.$broadcastel evento se propaga a todos los ámbitos secundarios, la mayoría de los cuales probablemente no serán oyentes de ese evento de todos modos. Y, por supuesto, al final del controlador receptor solo usa $rootScope.$on.

Para esta opción debes recordar destruir los oyentes rootScope del controlador:

var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
$scope.$on('$destroy', function () {
  unbindEventHandler();
});
thalisk avatar Apr 06 '2014 19:04 thalisk

¿Cómo puedo enviar mi objeto $scope de un controlador a otro usando los métodos .$emit y .$on?

Puedes enviar cualquier objeto que desees dentro de la jerarquía de tu aplicación, incluido $scope .

A continuación se ofrece una idea rápida sobre cómo funcionan la transmisión y la emisión .

Observe los nodos a continuación; todo anidado dentro del nodo 3. Usas transmisión y emisión cuando tienes este escenario.

Nota: El número de cada nodo en este ejemplo es arbitrario; fácilmente podría ser el número uno; el número dos; o incluso el número 1.348. Cada número es solo un identificador para este ejemplo. El objetivo de este ejemplo es mostrar el anidamiento de controladores/directivas Angular.

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

Mira este árbol. ¿Cómo respondes a las siguientes preguntas?

Nota: Hay otras formas de responder estas preguntas, pero aquí analizaremos la transmisión y la emisión . Además, al leer el texto a continuación, asuma que cada número tiene su propio archivo (directiva, controlador), por ejemplo, one.js, two.js, three.js.

¿ Cómo le habla el nodo 1 al nodo 3 ?

En el archivo uno.js

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

En el archivo three.js , el nodo superior para todos los nodos secundarios necesarios para comunicarse.

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

¿Cómo le habla el nodo 2 al nodo 3?

En el archivo dos.js

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

En el archivo three.js , el nodo superior para todos los nodos secundarios necesarios para comunicarse.

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

¿Cómo se comunica el nodo 3 con el nodo 1 y/o el nodo 2?

En el archivo three.js , el nodo superior para todos los nodos secundarios necesarios para comunicarse.

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

En el archivo one.js && two.js , cualquier archivo en el que desee capturar el mensaje o ambos.

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

¿Cómo le habla el nodo 2 al nodo 1?

En el archivo dos.js

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

En el archivo three.js , el nodo superior para todos los nodos secundarios necesarios para comunicarse.

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

En el archivo uno.js

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

SIN EMBARGO

Cuando tenga todos estos nodos secundarios anidados intentando comunicarse de esta manera, verá rápidamente muchos $on , $broadcast y $emit .

Esto es lo que me gusta hacer.

En el NODO PADRE superior ( 3 en este caso...), que puede ser su controlador principal...

Entonces, en el archivo tres.js

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

Ahora en cualquiera de los nodos secundarios solo necesita $emitir el mensaje o capturarlo usando $on .

NOTA: Normalmente es bastante fácil realizar conversaciones cruzadas en una ruta anidada sin usar $emit , $broadcast o $on , lo que significa que la mayoría de los casos de uso son para cuando intenta que el nodo 1 se comunique con el nodo 2 o viceversa.

¿Cómo le habla el nodo 2 al nodo 1?

En el archivo dos.js

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

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

En el archivo three.js , el nodo superior para todos los nodos secundarios necesarios para comunicarse.

Este ya lo manejamos ¿recuerdas?

En el archivo uno.js

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

Aún necesitarás usar $on con cada valor específico que quieras capturar, pero ahora puedes crear lo que quieras en cualquiera de los nodos sin tener que preocuparte por cómo hacer llegar el mensaje a través del espacio del nodo principal a medida que capturamos y transmitimos. el pushChangesToAllNodes genérico .

SoEzPz avatar Jul 11 '2015 14:07 SoEzPz

Para enviar $scope objectde un controlador a otro, hablaré sobre $rootScope.$broadcasty $rootScope.$emitaquí, ya que se utilizan con mayor frecuencia.

Caso 1 :

$rootScope.$transmisión:-

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

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

$rootScopeoyente no se destruyen automáticamente. Necesitas destruirlo usando $destroy. Es mejor usarlo $scope.$onya que los oyentes $scopese destruyen automáticamente, es decir, tan pronto como se destruye $scope.

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

O,

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

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

Caso 2:

$rootScope.$emitir:

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

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

La principal diferencia entre $emit y $broadcast es que el evento $rootScope.$emit debe escucharse usando $rootScope.$on, porque el evento emitido nunca baja a través del árbol de alcance. .
En este caso también debes destruir al oyente como en el caso de $broadcast.

Editar:

Prefiero no usar $rootScope.$broadcast + $scope.$onpero usar $rootScope.$emit+ $rootScope.$on. El $rootScope.$broadcast + $scope.$oncombo puede causar serios problemas de rendimiento. Esto se debe a que el evento se extenderá por todos los ámbitos.

Edición 2 :

El problema abordado en esta respuesta se resolvió en angular.js versión 1.2.7. $broadcast ahora evita la difusión en ámbitos no registrados y se ejecuta tan rápido como $emit.

Ved avatar Apr 02 '2016 18:04 Ved