Chỉnh sửa : Vấn đề được giải quyết trong câu trả lời này đã được giải quyết trong phiên bản angular.js 1.2.7 . $broadcastbây giờ tránh sủi bọt trên phạm vi chưa đăng ký và chạy nhanh như $ phát ra.

Vì vậy, bây giờ bạn có thể:
- sử dụng
$broadcasttừ$rootScope
- lắng nghe bằng cách sử dụng
$on từ địa phương$scope cần biết về sự kiện này
Câu trả lời gốc bên dưới
Tôi khuyên bạn không nên sử dụng $rootScope.$broadcast+ $scope.$onmà là $rootScope.$emit+ $rootScope.$on. Cái trước có thể gây ra vấn đề hiệu suất nghiêm trọng như được nêu ra bởi @numan. Đó là bởi vì sự kiện sẽ bong bóng xuống qua tất cả các phạm vi.
Tuy nhiên, cái sau (sử dụng $rootScope.$emit+ $rootScope.$on) không bị như vậy và do đó có thể được sử dụng như một kênh liên lạc nhanh!
Từ các tài liệu góc của $emit:
Gửi một tên sự kiện trở lên thông qua hệ thống phân cấp phạm vi thông báo đã đăng ký
Vì không có phạm vi ở trên $rootScope, không có bong bóng xảy ra. Hoàn toàn an toàn khi sử dụng $rootScope.$emit()/ $rootScope.$on()làm EventBus.
Tuy nhiên, có một gotcha khi sử dụng nó từ bên trong Bộ điều khiển. Nếu bạn liên kết trực tiếp $rootScope.$on()từ bên trong bộ điều khiển, bạn sẽ phải tự dọn sạch ràng buộc khi địa phương của bạn $scopebị phá hủy. Điều này là do các bộ điều khiển (trái ngược với các dịch vụ) có thể được khởi tạo nhiều lần trong suốt vòng đời của một ứng dụng dẫn đến các ràng buộc tóm tắt cuối cùng tạo ra rò rỉ bộ nhớ ở mọi nơi :)
Để unregister, chỉ cần lắng nghe trên của bạn $scope's $destroysự kiện và sau đó gọi hàm đã được trả về bởi $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);
}
]);
Tôi có thể nói, đó thực sự không phải là một điều cụ thể góc cạnh vì nó cũng áp dụng cho các triển khai EventBus khác, rằng bạn phải dọn sạch các tài nguyên.
Tuy nhiên, bạn có thể làm cho cuộc sống của bạn dễ dàng hơn cho những trường hợp đó. Chẳng hạn, bạn có thể vá khỉ $rootScopevà cho nó $onRootScopeđăng ký các sự kiện phát ra trên $rootScopenhưng cũng trực tiếp dọn sạch trình xử lý khi cục bộ $scopebị phá hủy.
Cách sạch nhất để khỉ vá phương pháp $rootScopecung cấp $onRootScopephương pháp như vậy là thông qua một người trang trí (một khối chạy có thể sẽ làm tốt như vậy nhưng pssst, đừng nói với ai)
Để đảm bảo $onRootScopetài sản không xuất hiện bất ngờ khi liệt kê $scopechúng tôi sử dụng Object.defineProperty()và đặt enumerablethành false. Hãy nhớ rằng bạn có thể cần một shim ES5.
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;
}]);
}]);
Với phương pháp này, mã điều khiển từ trên có thể được đơn giản hóa thành:
angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);
Vì vậy, như là kết quả cuối cùng của tất cả điều này, tôi khuyên bạn nên sử dụng $rootScope.$emit+ $scope.$onRootScope.
Btw, tôi đang cố gắng thuyết phục đội ngũ góc cạnh để giải quyết vấn đề trong lõi góc. Có một cuộc thảo luận đang diễn ra ở đây: https://github.com/angular/angular.js/issues/4574
Dưới đây là một jsperf cho thấy mức độ ảnh hưởng hoàn hảo $broadcastmang đến cho bảng trong một kịch bản hợp lý chỉ với 100 $scopegiây.
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
