907 Stimmen

Arbeiten mit $scope.$emit und $scope.$on

Wie kann ich meine $scope Objekt von einem Controller zu einem anderen mit .$emit y .$on Methoden?

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

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

Es funktioniert nicht so, wie ich es mir vorstelle. Wie funktioniert $emit y $on arbeiten?

1511voto

zbynour Punkte 19597

Zunächst einmal spielt die Beziehung zwischen Eltern und Kind eine Rolle. Sie haben zwei Möglichkeiten, ein Ereignis zu emittieren:

  • $broadcast -- gibt das Ereignis an alle untergeordneten Bereiche weiter,
  • $emit -- sendet das Ereignis nach oben durch die Bereichshierarchie.

Ich weiß nichts über die Beziehung zwischen Ihren Controllern (Scopes), aber es gibt mehrere Möglichkeiten:

  1. Wenn der Umfang der firstCtrl ist Elternteil des secondCtrl Bereich, sollte Ihr Code durch Ersetzen von $emit von $broadcast en firstCtrl :

    function firstCtrl($scope)
    {
        $scope.$broadcast('someEvent', [1,2,3]);
    }
    
    function secondCtrl($scope)
    {
        $scope.$on('someEvent', function(event, mass) { console.log(mass); });
    }
  2. Falls es keine Eltern-Kind-Beziehung zwischen Ihren Bereichen gibt, können Sie können Sie $rootScope in den Controller ein und senden das Ereignis an alle Child-Scopes (d.h. auch secondCtrl ).

    function firstCtrl($rootScope)
    {
        $rootScope.$broadcast('someEvent', [1,2,3]);
    }
  3. Schließlich, wenn Sie das Ereignis vom untergeordneten Controller aus versenden müssen aufwärts zu übertragen, können Sie $scope.$emit . Wenn der Umfang firstCtrl ist Elternteil des secondCtrl Umfang:

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

147voto

Thalis K. Punkte 6643

Ich würde zusätzlich eine 4. Option vorschlagen, die eine bessere Alternative zu den von @zbynour vorgeschlagenen Optionen darstellt.

Utilice $rootScope.$emit よりも $rootScope.$broadcast unabhängig von der Beziehung zwischen dem sendenden und dem empfangenden Kontrollgerät. Auf diese Weise bleibt das Ereignis in der Menge der $rootScope.$$listeners während bei $rootScope.$broadcast wird das Ereignis an alle untergeordneten Bereiche weitergegeben, von denen die meisten wahrscheinlich ohnehin nicht auf dieses Ereignis hören. Und natürlich verwendet man auf der Seite des empfangenden Controllers einfach $rootScope.$on .

Bei dieser Option müssen Sie daran denken, die rootScope-Listener des Controllers zu zerstören:

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

115voto

SoEzPz Punkte 13250

Wie kann ich mein $scope-Objekt von einem Controller zu einem anderen mit .$emit und .$on Methoden senden?

Sie können jedes beliebige Objekt innerhalb der Hierarchie Ihrer Anwendung senden, einschließlich $Umfang .

Hier eine kurze Vorstellung davon, wie Sendung y ausstrahlen. Arbeit.

Beachten Sie die folgenden Knoten, die alle innerhalb von Knoten 3 verschachtelt sind. Sie verwenden Sendung y ausstrahlen. wenn Sie dieses Szenario haben.

Anmerkung: Die Nummer eines jeden Knotens in diesem Beispiel ist willkürlich; es könnte leicht die Nummer eins, die Nummer zwei oder sogar die Nummer 1.348 sein. Jede Zahl ist nur ein Bezeichner für dieses Beispiel. Der Sinn dieses Beispiels ist es, die Verschachtelung von Angular-Controllern/Direktiven zu zeigen.

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

Sehen Sie sich diesen Baum an. Wie beantworten Sie die folgenden Fragen?

Anmerkung: Es gibt noch andere Möglichkeiten, diese Fragen zu beantworten, aber hier werden wir sie diskutieren Sendung y ausstrahlen. . Wenn Sie den folgenden Text lesen, gehen Sie davon aus, dass jede Nummer ihre eigene Datei hat (Richtlinie, Controller), z. B. one.js, two.js, three.js.

Wie funktioniert der Knoten 1 Knoten ansprechen 3 ?

In der Datei eins.js

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

In der Datei drei.js - des obersten Knotens an alle für die Kommunikation erforderlichen untergeordneten Knoten.

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

Wie spricht Knoten 2 mit Knoten 3?

In der Datei zwei.js

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

In der Datei drei.js - des obersten Knotens an alle für die Kommunikation erforderlichen untergeordneten Knoten.

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

Wie spricht Knoten 3 mit Knoten 1 und/oder Knoten 2?

In der Datei drei.js - des obersten Knotens an alle für die Kommunikation erforderlichen untergeordneten Knoten.

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

In der Datei eins.js && zwei.js die Datei, in der Sie die Nachricht abfangen wollen, oder beide.

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

Wie spricht Knoten 2 mit Knoten 1?

In der Datei zwei.js

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

In der Datei drei.js - des obersten Knotens an alle für die Kommunikation erforderlichen untergeordneten Knoten.

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

In der Datei eins.js

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

WIE AUCH IMMER

Wenn Sie all diese verschachtelten Kindknoten haben, die auf diese Weise zu kommunizieren versuchen, werden Sie schnell viele $on's , $Ausstrahlung und $mitts .

Das mache ich gerne.

Im obersten PARENT NODE ( 3 in diesem Fall... ), der möglicherweise Ihr übergeordneter Controller ist...

Also, in der Datei drei.js

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

In jedem der untergeordneten Knoten müssen Sie jetzt nur noch $mit die Nachricht oder fangen sie mit an .

HINWEIS: Normalerweise ist es recht einfach, in einem verschachtelten Pfad über Kreuz zu sprechen, ohne $mit , $Ausstrahlung , oder an Das heißt, die meisten Anwendungsfälle sind, wenn Sie versuchen, den Knoten 1 zur Kommunikation mit dem Knoten 2 oder andersherum.

Wie spricht Knoten 2 mit Knoten 1?

In der Datei zwei.js

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

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

In der Datei drei.js - des obersten Knotens an alle für die Kommunikation erforderlichen untergeordneten Knoten.

Wir haben das bereits erledigt, erinnern Sie sich?

In der Datei eins.js

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

Sie müssen noch Folgendes verwenden an mit jedem spezifischen Wert, den Sie abfangen wollen, aber jetzt können Sie in jedem der Knoten erstellen, was immer Sie wollen, ohne sich Gedanken darüber machen zu müssen, wie Sie die Nachricht über die Lücke des übergeordneten Knotens bekommen, da wir die generische pushChangesToAllNodes .

39voto

Ved Punkte 11418

Zum Senden $scope object von einem Controller zu einem anderen, werde ich über $rootScope.$broadcast y $rootScope.$emit hier, da sie am häufigsten verwendet werden.

Fall 1 :

$rootScope.$broadcast:-

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

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

$rootScope Hörer werden nicht automatisch zerstört. Sie müssen sie zerstören mit $destroy . Es ist besser zu verwenden $scope.$on als Hörer auf $scope werden automatisch zerstört, d.h. sobald $scope zerstört wird.

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

Oder,

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

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

Fall 2:

$rootScope.$emit:

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

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

Der Hauptunterschied zwischen $emit und $broadcast besteht darin, dass das Ereignis $rootScope.$emit mit $rootScope.$on abgehört werden muss, da das ausgesendete Ereignis nie durch den Scope-Baum nach unten gelangt. .
Auch in diesem Fall müssen Sie den Hörer wie im Fall von $broadcast zerstören.

Bearbeiten:

Ich ziehe es vor, nicht zu verwenden $rootScope.$broadcast + $scope.$on b $rootScope.$emit+ $rootScope.$on . Die $rootScope.$broadcast + $scope.$on Combo kann zu ernsthaften Leistungsproblemen führen. Das liegt daran weil das Ereignis durch alle Bereiche hindurch nach unten durchschlägt.

Bearbeiten 2 :

Das in dieser Antwort angesprochene Problem wurde in angular.js behoben Version 1.2.7 behoben. $broadcast vermeidet nun Bubbling über unregistrierte Scopes und läuft genau so schnell wie $emit.

10voto

kyasar Punkte 439

Sie müssen $rootScope verwenden, um Ereignisse zwischen Controllern in derselben Anwendung zu senden und zu erfassen. Injizieren Sie $rootScope Abhängigkeit zu Ihren Controllern. Hier ist ein funktionierendes Beispiel.

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

app.controller('secondCtrl', function($scope, $rootScope) {
        function secondCtrl($scope)
        {
            $rootScope.$on('someEvent', function(event, data) { console.log(data); });
        }
}

Ereignisse, die mit dem $scope-Objekt verknüpft sind, funktionieren nur im Eigentümer-Controller. Die Kommunikation zwischen Controllern erfolgt über $rootScope oder Services.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X