$ on ve $ açısal olarak yayın


282

Farklı görünümlere sahip bir footerController ve codeScannerController var.

angular.module('myApp').controller('footerController', ["$scope", function($scope) {}]);

angular.module('myApp').controller('codeScannerController', ["$scope", function($scope) {
console.log("start");
$scope.startScanner = function(){...

Bir <li>footer.html tıkladığında bu olayı codeScannerController almalısınız.

<li class="button" ng-click="startScanner()">3</li>

Bunun ile gerçekleştirilebilir düşünmek $onve $broadcastama ben bir yere örnekler bulamıyorum nasıl ve bilmiyorum.

Yanıtlar:


631

Eğer isterseniz $broadcastkullanın $rootScope:

$scope.startScanner = function() {

    $rootScope.$broadcast('scanner-started');
}

Ve sonra, almak $scopeiçin kumandanızı kullanın :

$scope.$on('scanner-started', function(event, args) {

    // do what you want to do
});

İsterseniz, aşağıdaki durumlarda bağımsız değişkenler iletebilirsiniz $broadcast:

$rootScope.$broadcast('scanner-started', { any: {} });

Ve sonra onları alın:

$scope.$on('scanner-started', function(event, args) {

    var anyThing = args.any;
    // do what you want to do
});

Scope belgelerinin içindeki belgeler .


2
Etkinliğe istediğiniz her şeyi adlandırabilirsiniz.
Davin Tryon

5
$ Scope olduğundan emin olun. $ Apply (); senin değişikliklerin!
İsmail

4
@Ismail Neden ... ve nerede?
Jaans

7
Bu dizeleri yayın mesajını kodlamak yerine bir yerde saklamak için önerilen uygulamalar var mı?
rperryng

8
@Ismail $scope.$apply()yalnızca modeli açısal çerçevenin dışında değiştirirken (setTimeout, iletişim kutusu geri çağrısı veya ajax geri çağrısında olduğu gibi) başka bir deyişle $apply(), tüm kodlar .$on()bittikten sonra tetiklenir .
th3uiguy

97

İlk olarak $on(), $broadcast()ve$emit() :

  • .$on(name, listener) - Belirli bir olayı belirli bir olay tarafından dinler name
  • .$broadcast(name, args) - Bir etkinliği $scope Tüm çocuklar
  • .$emit(name, args)- $scopeHiyerarşiyi tüm ebeveynlere,$rootScope

Aşağıdaki HTML'yi temel alarak ( buradaki tam örneğe bakın ):

<div ng-controller="Controller1">
    <button ng-click="broadcast()">Broadcast 1</button>
    <button ng-click="emit()">Emit 1</button>
</div>

<div ng-controller="Controller2">
    <button ng-click="broadcast()">Broadcast 2</button>
    <button ng-click="emit()">Emit 2</button>
    <div ng-controller="Controller3">
        <button ng-click="broadcast()">Broadcast 3</button>
        <button ng-click="emit()">Emit 3</button>
        <br>
        <button ng-click="broadcastRoot()">Broadcast Root</button>
        <button ng-click="emitRoot()">Emit Root</button>
    </div>
</div>

İşten çıkarılan olaylar $scopesaşağıdaki gibi geçecektir :

  • Yayın 1 - Yalnızca Denetleyici 1 tarafından görülecektir $scope
  • Emit 1 - Kontrolör 1 tarafından görülebilir Will $scopesonra$rootScope
  • Yayın 2 - Kontrolör 2 $scopesonra Kontrolör 3 tarafından görülecektir$scope
  • Emit 2 - Kontrolör 2 tarafından görülebilir Will $scopesonra$rootScope
  • Yayın 3 - Yalnızca Kontrolör 3 tarafından görülecektir $scope
  • Emit 3 - Kontrolör 3 tarafından görülebilir Will $scope, Kontrolör 2 $scopesonra$rootScope
  • Yayın Kök - tarafından görülebilir Will $rootScopeve $scope(daha sonra 1 3 2) tüm Kontrolörleri
  • Kök Yaymak - Yalnızca $rootScope

Etkinlikleri tetiklemek için JavaScript (yine burada çalışan bir örnek görebilirsiniz ):

app.controller('Controller1', ['$scope', '$rootScope', function($scope, $rootScope){
    $scope.broadcastAndEmit = function(){
        // This will be seen by Controller 1 $scope and all children $scopes 
        $scope.$broadcast('eventX', {data: '$scope.broadcast'});

        // Because this event is fired as an emit (goes up) on the $rootScope,
        // only the $rootScope will see it
        $rootScope.$emit('eventX', {data: '$rootScope.emit'});
    };
    $scope.emit = function(){
        // Controller 1 $scope, and all parent $scopes (including $rootScope) 
        // will see this event
        $scope.$emit('eventX', {data: '$scope.emit'});
    };

    $scope.$on('eventX', function(ev, args){
        console.log('eventX found on Controller1 $scope');
    });
    $rootScope.$on('eventX', function(ev, args){
        console.log('eventX found on $rootScope');
    });
}]);

vermiş olduğunuz örnekle uygulamamın hiyerarşisini nasıl hayal edebilirim. Bir kontrolör nasıl ebeveyn veya çocuk olabilir? Söylemeye çalıştığım, bir dizi devlete sahip olduğum. LoginCtrl -> homeCrl -> bildirimCtrl vb.
HIRA THAKUR

26

Bilmeniz gereken bir şey $ öneki bir Açısal Yöntemi, $$ önekleri kullanmaktan kaçınmanız gereken açısal yöntemleri ifade eder.

Aşağıda örnek bir şablon ve denetleyicileri, $ broadcast / $ on öğesinin istediğimizi gerçekleştirmemize nasıl yardımcı olabileceğini keşfedeceğiz.

<div ng-controller="FirstCtrl">
    <input ng-model="name"/> 
    <button ng-click="register()">Register </button>
</div>

<div ng-controller="SecondCtrl">
    Registered Name: <input ng-model="name"/> 
</div>

Kontrolörler

app.controller('FirstCtrl', function($scope){
    $scope.register = function(){

    }
});

app.controller('SecondCtrl', function($scope){

});

Size sorum, kullanıcı kayıt tıkladığında adı ikinci denetleyiciye nasıl ilettiğinizdir. Birden fazla çözüm bulabilirsiniz, ancak kullanacağımız $ broadcast ve $ on kullanıyor.

$ yayın vs $ emit

Hangisini kullanmalıyız? $ broadcast tüm alt dom öğelerine kanalize olur ve $ emit tüm ata dom öğelerine ters yönde kanal gönderir.

$ Emit veya $ broadcast arasında karar vermekten kaçınmanın en iyi yolu $ rootScope'tan kanal açmak ve tüm çocuklarına $ broadcast kullanmaktır. Bu da dom elemanlarımız kardeş olduğu için davamızı daha kolay hale getiriyor.

$ RootScope ekleme ve $ yayınlama imkanı

app.controller('FirstCtrl', function($rootScope, $scope){
    $scope.register = function(){
        $rootScope.$broadcast('BOOM!', $scope.name)
    }
});

$ RootScope eklediğimizi ve şimdi $ broadcast (broadcastName, argümanlar) kullandığımızı unutmayın. BroadcastName için, bu adı secondCtrl dosyamızda yakalayabilmemiz için benzersiz bir ad vermek istiyoruz. BOOM'u seçtim! sadece eğlence için. İkinci argüman olan 'argümanlar' dinleyicilere değer aktarmamızı sağlar.

Yayınımızı almak

İkinci denetleyicimizde, yayınımızı dinlemek için kod ayarlamamız gerekiyor

app.controller('SecondCtrl', function($scope){
  $scope.$on('BOOM!', function(events, args){
    console.log(args);
    $scope.name = args; //now we've registered!
  })
});

Gerçekten bu kadar basit. Canlı Örnek

Benzer sonuçlara ulaşmanın diğer yolları

Bu yöntem paketini kullanmaktan kaçınmaya çalışın, çünkü ne etkili ne de bakımı kolaydır, ancak sahip olabileceğiniz sorunları düzeltmenin basit bir yoludur.

Aynı şeyi genellikle bir hizmet kullanarak veya denetleyicilerinizi basitleştirerek de yapabilirsiniz. Bunu ayrıntılı olarak tartışmayacağız ama sadece bütünlük için bahsedeceğimi düşündüm.

Son olarak, dinlemek için gerçekten yararlı bir yayının '$ destroy' olduğunu unutmayın, $ 'ın satıcı kodları tarafından oluşturulan bir yöntem veya nesne olduğunu görebilirsiniz. Her neyse $ destroy bir denetleyici yok edildiğinde yayınlanır, denetleyicinizin ne zaman kaldırıldığını öğrenmek için bunu dinlemek isteyebilirsiniz.


2
Uyarı olarak, uygulamanızda çok fazla yayın / yayın kullanmamaya çalışın. Özellikle büyük bir uygulamada yönetmek son derece zor olabilir, çünkü bu olayların köklerini izlemek çok zor bir iştir.
Yang Li

1
//Your broadcast in service

(function () { 
    angular.module('appModule').factory('AppService', function ($rootScope, $timeout) {

    function refreshData() {  
        $timeout(function() {         
            $rootScope.$broadcast('refreshData');
        }, 0, true);      
    }

    return {           
        RefreshData: refreshData
    };
}); }());

//Controller Implementation
 (function () {
    angular.module('appModule').controller('AppController', function ($rootScope, $scope, $timeout, AppService) {            

       //Removes Listeners before adding them 
       //This line will solve the problem for multiple broadcast call                             
       $scope.$$listeners['refreshData'] = [];

       $scope.$on('refreshData', function() {                                                    
          $scope.showData();             
       });

       $scope.onSaveDataComplete = function() { 
         AppService.RefreshData();
       };
    }); }());
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.