Düzenleme : Bu yanıtta ele alınan sorun angular.js sürüm 1.2.7'de giderilmiştir . $broadcast
şimdi kayıt dışı kapsamlar üzerinde kabarcık oluşmasını önler ve $ emit kadar hızlı çalışır.
Şimdi şunları yapabilirsiniz:
- kullanmak
$broadcast
gelen$rootScope
- etkinlik hakkında bilmeniz gereken
$on
yerelden$scope
kullanarak dinleyin
Aşağıda Orijinal Yanıt
Çok kullanmamayı tavsiye $rootScope.$broadcast
+ $scope.$on
ziyade ancak $rootScope.$emit
+ $rootScope.$on
. Birincisi @ insan tarafından ortaya konulduğu gibi ciddi performans sorunlarına neden olabilir. Bunun nedeni, olayın tüm kapsamlar boyunca patlayacağıdır.
Ancak, ikincisi ( $rootScope.$emit
+ kullanarak $rootScope.$on
) bundan muzdarip değildir ve bu nedenle hızlı bir iletişim kanalı olarak kullanılabilir!
Açısal dokümanlarından $emit
:
Kayıtlıyı bildiren kapsam hiyerarşisinde yukarı doğru bir olay adı gönderir
Yukarıda bir kapsam $rootScope
olmadığından, kabarcıklanma olmaz. EventBus olarak $rootScope.$emit()
/ kullanmak tamamen güvenlidir $rootScope.$on()
.
Ancak, Kontrolörler içinden kullanırken bir tane var. $rootScope.$on()
Bir denetleyiciden doğrudan bağlanırsanız , $scope
yereliniz yok edildiğinde bağlamayı kendiniz temizlemeniz gerekir . Bunun nedeni, denetleyicilerin (hizmetlerin aksine), uygulamanın ömrü boyunca birden çok kez örneklenebilmesidir;
Unregister için, sadece dinlemek $scope
bireyin $destroy
olay ve o sırada döndürüldü işlevini çağırmak $rootScope.$on
.
angular
.module('MyApp')
.controller('MyController', ['$scope', '$rootScope', function MyController($scope, $rootScope) {
var unbind = $rootScope.$on('someComponent.someCrazyEvent', function(){
console.log('foo');
});
$scope.$on('$destroy', unbind);
}
]);
Diğer EventBus uygulamaları için de geçerli olduğu için gerçekten açısal bir şey değil, kaynakları temizlemeniz gerektiğini söyleyebilirim.
Ancak, olabilir bu durumlar için hayatınızı kolaylaştıracak. Örneğin, maymun yaması $rootScope
verebilir ve ona $onRootScope
yayılan olaylara abone olan, $rootScope
ancak yerel $scope
imha edildiğinde doğrudan işleyiciyi temizleyen bir öğe verebilirsiniz .
$rootScope
Böyle bir $onRootScope
yöntemi sağlamak için maymun yamasının en temiz yolu bir dekoratör aracılığıyla olacaktır (bir çalışma bloğu muhtemelen iyi de yapar, ancak pssst, kimseye söyleme)
Emin olmak için $onRootScope
üzerinde numaralandırılıyor mülkiyet beklenmedik görünmüyor $scope
kullandığımız Object.defineProperty()
ve set enumerable
için false
. Bir ES5 şimine ihtiyacınız olabileceğini unutmayın.
angular
.module('MyApp')
.config(['$provide', function($provide){
$provide.decorator('$rootScope', ['$delegate', function($delegate){
Object.defineProperty($delegate.constructor.prototype, '$onRootScope', {
value: function(name, listener){
var unsubscribe = $delegate.$on(name, listener);
this.$on('$destroy', unsubscribe);
return unsubscribe;
},
enumerable: false
});
return $delegate;
}]);
}]);
Bu yöntem uygulandığında, yukarıdan kontrolör kodu basitleştirilebilir:
angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);
Tüm bunların nihai sonucu olarak $rootScope.$emit
+ kullanmanızı şiddetle tavsiye ederim $scope.$onRootScope
.
Btw, açısal ekibi problemi açısal çekirdek içinde ele almaya ikna etmeye çalışıyorum. Burada bir tartışma var: https://github.com/angular/angular.js/issues/4574
İşte sadece 100'lerle $broadcast
iyi bir senaryoda mükemmel bir etkinin ne kadarını masaya getirdiğini gösteren bir jsperf $scope
.
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast