web-dev-qa-db-ja.com

$ rootScope。$ broadcastと$ scopeの比較

$broadcast$emitのパフォーマンスの違いがなくなったので、$scope.$emitより$rootScope.$broadcastを選ぶ理由はありますか?

彼らは違います、そうです。

$emitはスコープ階層(上向き)に制限されています - あなたの設計に合うのであればこれは良いかもしれませんが、それは私にはかなり恣意的な制限のようです。

$rootScope.$broadcastはすべてのものに渡って動作します イベントを監視するには を選択します。これは私の考えではより賢明な制限です。

私は何かが足りないのですか?

編集:

答えに答えて明確にするために、派遣の方向は私が後にする問題ではありません。 $scope.$emitはイベントを上向きに、$scope.$broadcast - は下向きにディスパッチします。しかし、意図したすべてのリスナーに到達するために常に$rootScope.$broadcastを使用しないのはなぜですか?

341
New Dev

tl; dr (このtl; drは @ sp00m からの回答です)

$emitはイベントを上にディスパッチします... $broadcastはイベントを下にディスパッチします

詳細説明

$rootScope.$emitは他の$rootScopeリスナーにそれを捕らえるだけです。すべての$scopeにそれを取得させたくない場合、これは良いことです。主に高レベルのコミュニケーション。子供がそれらを聞くことができないように大人が部屋の中で互いに話していると考えてください。

$rootScope.$broadcastは、ほとんどすべてのものにそれを聞かせる方法です。これは両親が夕食の準備ができていると叫んでいるので、家の中の誰もがそれを聞くことに相当します。

$scope.$emitは、その$scopeとそのすべての親、そして$rootScopeにそのイベントを聞かせたいときです。これは自宅で両親に泣き言を言う子供です(ただし、他の子供たちが聞くことができる食料品店ではありません)。

$scope.$broadcast$scope自身とその子供たちのためのものです。これは彼らの両親が聞くことができないようにぬいぐるみにささやく子供です。

1125
Eddie Monge Jr

$emitはスコープの階層を通してイベント upwards を送りますが、$broadcastはすべての子スコープにイベント downwards を送ります。

103
sp00m

私は次のリンクから次の図を作りました: https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Scope, rootScope, emit, broadcast

ご覧のとおり、$rootScope.$broadcast$scope.$emitよりもはるかに多くのリスナーにヒットしています。

また、$scope.$emitのバブリング効果は取り消すことができますが、$rootScope.$broadcastは取り消すことができません。

76

enter image description here

$ scope。$ emit:このメソッドはイベントを上方向(子から親へ)に振り分けます。

enter image description here $ scope。$ broadcast:メソッドはイベントを(親から子への)下方向にすべての子コントローラに送ります。

enter image description here $ scope。$ on:メソッドは何らかのイベントを監視するために登録します。そのイベントをリッスンしているすべてのコントローラは、ブロードキャスト通知を受け取るか、子 - 親階層のどこに収まるかに基づいて発信します。

$ emitイベントは、そのイベントをリッスンしているすべての$スコープによってキャンセルすることができます。

$ onは "stopPropagation"メソッドを提供します。このメソッドを呼び出すことで、イベントがそれ以上伝播しないようにすることができます。

プランカー: https://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/ /

兄弟スコープ(直接の親子階層にないスコープ)の場合、$ emitと$ broadcastは兄弟スコープと通信しません。

enter image description here

詳細については http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html を参照してください。

17
Yogesh

@Eddieは、質問に対する完璧な回答をしています。しかし、Pub/Subのより効率的なアプローチの使用に注意を向けたいと思います。

これ 答えが示唆するように、

$ broadcast/$ onアプローチはすべてのスコープにブロードキャストするので(スコープ階層の一方向または両方向に)、あまり効率的ではありません。 Pub/Subアプローチはもっと直接的です。購読者だけがイベントを取得するため、システム内のすべての範囲でイベントを機能させるわけではありません。

angular-PubSub angularモジュールを使うことができます。アプリの依存関係にPubSubモジュールを追加したら、PubSubサービスを使用してイベント/トピックを購読および購読解除できます。

簡単に購読できます。

// Subscribe to event
var sub = PubSub.subscribe('event-name', function(topic, data){

});

公開が簡単

PubSub.publish('event-name', {
    prop1: value1,
    prop2: value2
});

購読を中止するには、PubSub.unsubscribe(sub); OR PubSub.unsubscribe('event-name');を使用します。

_ note _ メモリリークを防ぐために登録解除することを忘れないでください。

3
vinesh

サービスでRxJSを使用する

例えば、あなたが状態を保持しているサービスを持っている状況ではどうでしょうか。そのサービスへの変更をプッシュし、ページ上の他のランダムな要素はそのような変更をどのように認識することができますか?最近この問題に取り組むのに苦労している

RxJS Extensions for Angular を使用してサービスを構築します。

<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/rx/dist/rx.all.js"></script>
<script src="//unpkg.com/rx-angular/dist/rx.angular.js"></script>
var app = angular.module('myApp', ['rx']);

app.factory("DataService", function(rx) {
  var subject = new rx.Subject(); 
  var data = "Initial";

  return {
      set: function set(d){
        data = d;
        subject.onNext(d);
      },
      get: function get() {
        return data;
      },
      subscribe: function (o) {
         return subject.subscribe(o);
      }
  };
});

それから変更を購読してください。

app.controller('displayCtrl', function(DataService) {
  var $ctrl = this;

  $ctrl.data = DataService.get();
  var subscription = DataService.subscribe(function onNext(d) {
      $ctrl.data = d;
  });

  this.$onDestroy = function() {
      subscription.dispose();
  };
});

クライアントはDataService.subscribeで変更を購読することができ、プロデューサーはDataService.setで変更をプッシュすることができます。

PLNKR上のデモ

2
georgeawg