$ rootScope. $ yayın vs $ kapsam. $ emit


349

Şimdi $broadcastve arasındaki performans farkı $emitgiderildiğine göre, tercih $scope.$emitetmek için herhangi bir neden var $rootScope.$broadcastmı?

Farklılar, evet.

$emit kapsam hiyerarşisiyle sınırlıdır (yukarı doğru) - tasarımınıza uyuyorsa iyi olabilir, ancak bana oldukça keyfi bir kısıtlama geliyor.

$rootScope.$broadcastaklıma daha mantıklı bir kısıtlama olan olayı dinlemeyi seçen her şeyde çalışıyor.

Bir şey mi kaçırıyorum?

DÜZENLE:

Bir cevaba yanıt olarak açıklığa kavuşturmak için, sevkıyatın yönü peşinde olduğum sorun değil. $scope.$emitolayı yukarı ve $scope.$broadcast- aşağı gönderir . Ama neden her zaman $rootScope.$broadcasttüm dinleyicilere ulaşmak için kullanmıyorsunuz ?


Yanıtlar:


1155

tl; dr (bu tl; dr aşağıdaki @ sp00m'nin cevabından alınmıştır )

$emitbir olayı yukarı $broadcastgönderir ... bir olayı aşağı gönderir

Detaylı açıklama

$rootScope.$emitsadece diğer $rootScopedinleyicilerin yakalamasına izin verir . Bu, herkesin $scopealmasını istemediğinizde iyidir . Çoğunlukla üst düzey bir iletişim. Çocukların onları duyamaması için bir odada birbirleriyle konuşan yetişkinler olarak düşünün.

$rootScope.$broadcasthemen hemen her şeyin duymasını sağlayan bir yöntemdir. Bu, akşam yemeğinin hazır olduğunu söyleyen ebeveynlerin eşdeğeridir, böylece evdeki herkes onu duyar.

$scope.$emitbunu $scopeve tüm ebeveynlerini istediğiniz zaman $rootScopeve olayı duymaktır. Bu, ebeveynlerine evde sızlanan bir çocuktur (ancak diğer çocukların duyabileceği bir bakkalda değil).

$scope.$broadcastiçindir $scopekendisi ve çocukları. Bu, doldurulmuş hayvanlarına fısıldayan bir çocuktur, böylece ebeveynleri duyamaz.


3
@NewDev Nedeni, sayfadaki kapsamların sık sık tekrarlanmasıdır. Farklı veri örneklerini temsil eden iki veya daha fazla kapsamınız varsa (örneğin, her biri kendi kapsamına sahip bir sayfadaki hasta kayıtlarının listesi), yalnızca bunlardan biri için tasarlanmış bir etkinliği kökten yayınlamak için çalışmaz kapsamları. $rootScopeMümkün olan yerlerde yayınlardan kaçınmak daha iyi bir kullanım sağlar.
Tim Rogers

4
Söylediğiniz hiçbir şey yanlış değildir, ancak $ emit'in belgeyi alt kapsamlara ve $ emit'in belgenin üst kapsamlarına çıkmasını genelleştirmenin bir yolu. Her ikisi de geçerli kapsama bağlı dinleyicileri tetikler.
Eric

123
Kullandığınız örnek harika!
Assaf

72
Vaov! Çocuklar bile bunu anlayabilir! İnanılmaz :)
Navaneeth

3
Mükemmel bir örnek, açıklamayı seviyorum
Robin-Hoodie

104

Aynı işi yapmıyorlar: $emitbir olayı kapsam hiyerarşisinde yukarı doğru$broadcast gönderirken , tüm alt kapsamlara aşağı doğru bir olay gönderir .


2
Evet, soruda belirtmiştim (belki de sevkıyatın yönünü açıklığa kavuşturabilirdim). Ancak bunun oldukça keyfi bir kısıtlama olduğunu da belirttim. Eğer "dinleyicime" ulaşabilirsem, bunu neden hep aşağıdan yapamıyorum $rootScope?
Yeni Dev

Çünkü $ emit bir kapsamın alt veya kardeş kapsamlarını etkilemez. Bunlar sadece javascript'in olay yayma türleriyle eşleşir - yakalama ve köpürme. Yakalama için $ broadcast ve köpürme için $ emit kullanılır. Farkı oldukça iyi açıklayan şimdi eski görünen bir quirksmode makalesi var: quirksmode.org/js/events_order.html
Alan L.

77

Aşağıdaki bağlantıdan aşağıdaki grafiği yaptım: https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Kapsam, rootScope, yayın, yayın

Gördüğünüz gibi, $rootScope.$broadcastdinleyiciden çok daha fazla dinleyici vuruyor $scope.$emit.

Ayrıca, $scope.$emit's köpürme etkisi iptal edilebilir, ancak $rootScope.$broadcastolamaz.


24
Bir sürü ok görüyorum.
Mars Robertson

4
@MichalStefanow Ben görsel cevapların hayranıyım :)
Maria Ines Parnisari

@mparnisari:. $ broadcast (name, args) - Bir etkinliği tüm çocukların $ kapsamı boyunca yayınlar. $ emit (name, args) - $ rootScope dahil tüm ebeveynlere $ scope hiyerarşisinde bir etkinlik yayınlar
CodeMan

19

resim açıklamasını buraya girin

$ scope. $ emit: Bu yöntem olayı yukarı yönde gönderir (alt öğeden üst öğeye)

resim açıklamasını buraya girin $ scope. $ broadcast: Yöntem, olayı aşağı doğru yönde (ebeveynden çocuğa) tüm alt denetleyicilere gönderir.

resim açıklamasını buraya girin $ scope. $ on: Yöntem bazı olayları dinlemek için kaydolur. Bu olayı dinleyen tüm denetleyiciler, alt-ebeveyn hiyerarşisine nerelere sığdıklarına bağlı olarak yayın hakkında bildirim alır veya yayın yapar.

$ Emit olayı, olayı dinleyen $ kapsamından herhangi biri tarafından iptal edilebilir.

$ On "stopPropagation" yöntemini sağlar. Bu yöntemi çağırarak olayın daha fazla yayılması durdurulabilir.

Plunker: https://embed.plnkr.co/0Pdrrtj3GEnMp2UpILp4/

Kardeş kapsamları (doğrudan üst-alt hiyerarşisinde olmayan kapsamlar) durumunda, $ emit ve $ broadcast kardeş kapsamlarıyla iletişim kuramaz.

resim açıklamasını buraya girin

Daha fazla ayrıntı için lütfen http://yogeshtutorials.blogspot.in/2015/12/event-based-communication-between-angularjs-controllers.html adresine bakın.


Bir çözümün bağlantısı hoş karşılanır, ancak lütfen cevabınızın onsuz faydalı olduğundan emin olun: bağlantınızın çevresine bağlam ekleyin, böylece diğer kullanıcılarınız ne olduğu ve neden orada olduğu hakkında bir fikir sahibi olacak, ardından sayfanın en alakalı bölümünü alıntılayacağız ' hedef sayfanın kullanılamaması durumunda bağlantı kuruluyor. Bir bağlantıdan biraz daha fazlası olan yanıtlar silinebilir.
Baum mit Augen

Amaç, çalışan dalma pistonunu sağlamaktı, ancak buraya uygun açıklamayı ekledim.
Yogesh

3

@Eddie sorulan soruya mükemmel bir cevap verdi. Ancak daha verimli bir Pub / Sub yaklaşımına dikkat çekmek istiyorum.

Gibi bu sorunun cevabı da anlaşılacağı

$ Broadcast / $ on yaklaşımı, tüm kapsamlara yayın yaptığı için çok etkili değildir (ya bir yönde ya da Kapsam hiyerarşisinin her iki yönünde). Pub / Sub yaklaşımı ise çok daha doğrudan. Yalnızca aboneler olayları alır, bu nedenle sistemdeki her kapsamın çalışmasını sağlamaz.

angular-PubSubaçısal modül kullanabilirsiniz . PubSubuygulama bağımlılığınıza modül ekledikten sonra , PubSubetkinliklere / konulara abone olmak ve abonelikten çıkmak için hizmeti kullanabilirsiniz .

Abone olmak kolay:

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

});

Yayınlanması kolay

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

, Abonelikten kullanım için PubSub.unsubscribe(sub);VEYA PubSub.unsubscribe('event-name');.

NOT Bellek sızıntılarını önlemek için abonelikten çıkmayı unutmayın.


2

Bir Hizmette RxJS Kullanın

Örneğin, durumu tutan bir Hizmetinizin olduğu bir durumda. Bu Hizmette yapılan değişiklikleri nasıl iletebilirim ve sayfadaki diğer rastgele bileşenler bu değişikliğin farkında olabilir mi? Son zamanlarda bu sorunun üstesinden gelmek için mücadele ediyor

Angular için RxJS Extensions ile bir servis oluşturun .

<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);
      }
  };
});

Ardından değişikliklere abone olun.

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();
  };
});

Müşteriler ile değişikliklere abone olabilir DataService.subscribeve üreticiler ile değişiklikleri zorlayabilir DataService.set.

PLNKR üzerinde DEMO .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.