แก้ไข : ปัญหาการแก้ไขในคำตอบนี้ได้รับการแก้ไขใน angular.js เวอร์ชัน 1.2.7 $broadcastตอนนี้หลีกเลี่ยงการเดือดดาลเหนือขอบเขตที่ไม่ได้ลงทะเบียนและทำงานได้เร็วเท่ากับ $ emit

ดังนั้นตอนนี้คุณสามารถ:
- ใช้
$broadcastจาก$rootScope
- ฟังการใช้งาน
$on จากท้องถิ่น$scopeที่จำเป็นต้องรู้เกี่ยวกับเหตุการณ์
คำตอบเดิมด้านล่าง
ผมขอให้คำแนะนำที่จะไม่ใช้$rootScope.$broadcast+ $scope.$onแต่+$rootScope.$emit $rootScope.$onอดีตอาจทำให้เกิดปัญหาประสิทธิภาพการทำงานที่ร้ายแรงโดย @numan นั่นเป็นเพราะเหตุการณ์จะทำให้ฟองดูในขอบเขตทั้งหมด
อย่างไรก็ตามหลัง (ใช้$rootScope.$emit+ $rootScope.$on) ไม่ประสบกับสิ่งนี้และสามารถใช้เป็นช่องทางการสื่อสารที่รวดเร็ว!
จากเอกสารเชิงมุมของ$emit:
ยื้อชื่อเหตุการณ์ขึ้นไปตามลำดับชั้นขอบเขตแจ้งการลงทะเบียน
เนื่องจากไม่มีขอบเขตด้านบน$rootScopeจึงไม่มีการเดือดปุด ๆ มีความปลอดภัยทั้งหมดที่จะใช้$rootScope.$emit()/ $rootScope.$on()เป็น EventBus
อย่างไรก็ตามมีหนึ่ง gotcha เมื่อใช้มันจากภายในตัวควบคุม ถ้าคุณผูกโดยตรง$rootScope.$on()จากภายในตัวควบคุมคุณจะต้องทำความสะอาดตัวเองเมื่อท้องถิ่นของคุณ$scopeถูกทำลาย นี่เป็นเพราะตัวควบคุม (ตรงกันข้ามกับบริการ) สามารถรับอินสแตนซ์ได้หลายครั้งตลอดอายุการใช้งานของแอปพลิเคชันซึ่งจะส่งผลให้เกิดการสรุปรวมในที่สุดการสร้างหน่วยความจำรั่วทั่วสถานที่ :)
ถอนการลงทะเบียนเพียงแค่ฟังคุณ$scope's เหตุการณ์แล้วเรียกฟังก์ชั่นที่ถูกส่งกลับโดย$destroy$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);
}
]);
ฉันจะบอกว่านั่นไม่ใช่สิ่งที่เฉพาะเจาะจงเชิงมุมเพราะมันใช้กับการใช้งาน EventBus อื่น ๆ เช่นกันว่าคุณต้องทำความสะอาดทรัพยากร
อย่างไรก็ตามคุณสามารถทำให้ชีวิตของคุณง่ายขึ้นสำหรับกรณีเหล่านั้น ตัวอย่างเช่นคุณสามารถแก้ไขลิง$rootScopeและให้มัน$onRootScopeที่สมัครสมาชิกกับเหตุการณ์ที่ปล่อยออกมาใน$rootScopeแต่ยังทำความสะอาดตัวจัดการโดยตรงเมื่อท้องถิ่น$scopeถูกทำลาย
วิธีที่สะอาดที่สุดในการติดตั้งลิง$rootScopeเพื่อให้$onRootScopeวิธีการดังกล่าวคือผ่านมัณฑนากร
เพื่อให้แน่ใจว่า$onRootScopeคุณสมบัติไม่ปรากฏขึ้นไม่คาดคิดเมื่อแจงมากกว่า$scopeที่เราใช้Object.defineProperty()และการตั้งค่าไปenumerable falseโปรดทราบว่าคุณอาจต้องการ ES5 shim
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;
}]);
}]);
ด้วยวิธีนี้ในสถานที่รหัสควบคุมจากด้านบนสามารถง่ายต่อการ:
angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);
เพื่อให้เป็นผลสุดท้ายของทั้งหมดนี้ผมขอแนะนำให้คุณใช้+$rootScope.$emit$scope.$onRootScope
Btw ฉันพยายามโน้มน้าวให้ทีมงานเชิงมุมเพื่อแก้ไขปัญหาภายในแกนเชิงมุม มีการสนทนาเกิดขึ้นที่นี่: https://github.com/angular/angular.js/issues/4574
นี่คือ jsperf ที่แสดงให้เห็นว่าผลกระทบที่สมบูรณ์แบบ$broadcastนำมาสู่ตารางในสถานการณ์ที่ดีเพียง 100 $scopeเท่านั้น
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
