it-swarm.com.de

Wie kann man Broadcast-Ereignisse in AngularJS stoppen?

Gibt es einen integrierten Weg, um $broadcast-Ereignisse daran zu hindern, die Scope-Kette zu durchlaufen?

Das Ereignisobjekt, das von einem $broadcast-Ereignis übergeben wird, verfügt nicht über eine stopPropagation-Methode (wie in docs in $ rootScope erwähnt.). Diese zusammengeführte Pull-Anforderung schlägt jedoch vor, dass $broadcast-Ereignisse stopPropagation aufgerufen werden können.

30
Noah Freitas

Ausschnitte aus dem Quellcode von angleJS 1.1.2:

$emit: function(name, args) {
    // ....
    event = {
        name: name,
        targetScope: scope,
        stopPropagation: function() {
            stopPropagation = true;
        },
        preventDefault: function() {
            event.defaultPrevented = true;
        },
        defaultPrevented: false
    },
    // ....
}

$broadcast: function(name, args) {
    // ...
    event = {
        name: name,
        targetScope: target,
        preventDefault: function() {
            event.defaultPrevented = true;
        },
        defaultPrevented: false
    },
    // ...
}

Wie Sie sehen können, haben Ereignisobjekte in $ broadcast nicht "stopPropagation".

Anstelle von stopPropagation können Sie mittels removeDefault ein Ereignis als "dieses Ereignis nicht verarbeiten" kennzeichnen. Damit wird die Weitergabe von Ereignissen nicht gestoppt, aber dies sagt den untergeordneten Bereichen: "Dieses Ereignis muss nicht verarbeitet werden".

Beispiel: http://jsfiddle.net/C8EqT/1/

43
kostik

Da Broadcast nicht über die Methode stopPropagation verfügt, müssen Sie die Eigenschaft defaultPrevented verwenden. Dies ist bei rekursiven Anweisungen sinnvoll.

Schauen Sie sich diesen Plunker hier an: Plunkr

$scope.$on('test', function(event) { if (!event.defaultPrevented) { event.defaultPrevented = true; console.log('Handle event here for the root node only.'); } });

7
Mahendra Singh

Ich habe für diesen Zweck einen Eventdieb implementiert:

.factory("stealEvent", [function () {

  /**
   * If event is already "default prevented", noop.
   * If event isn't "default prevented", executes callback.
   * If callback returns a truthy value or undefined,
   * stops event propagation if possible, and flags event as "default prevented".
   */
  return function (callback) {
    return function (event) {
      if (!event.defaultPrevented) {
        var stopEvent = callback.apply(null, arguments);
        if (typeof stopEvent === "undefined" || stopEvent) {
          event.stopPropagation && event.stopPropagation();
          event.preventDefault();
        }
      }
    };
  };

}]);

Benutzen:

$scope.$on("AnyEvent", stealEvent(function (event, anyOtherParameter) {
  if ($scope.keepEvent) {
    // do some stuff with anyOtherParameter
    return true; // steal event
  } else {
    return false; // let event available for other listeners
  }
}));

$scope.$on("AnyOtherEvent", stealEvent(function (event, anyOtherParameter) {
  // do some stuff with anyOtherParameter, event stolen by default
}));
1
sp00m