我有一个Angular控制器,一个相当简单的控制器:
angular.controller('appCtrl', function ($scope, $rootScope) {
$rootscope.$on('channel.message', function () {
// do stuff here
}
});
我的页面上有一些侧边栏,它会导航我到上面附带控制器的视图。
问题在于,每次点击链接时,Angular都会实例化控制器 - 这完全没问题,但我可以看到我'channel.message'
的订阅者数量正在增长,这不是我想要的是。
我理解,嗯,代码只是添加了另一个回调队列,但我希望避免这个问题。我只想要一个订阅者。这里的最佳做法是什么?
BTW:我知道 $ scope 。$ on。由于应用程序本身的性能影响和架构设计,它不算数。
答案 0 :(得分:3)
也许尝试在命名函数中调用您的事件处理程序,该函数将调用它并清理它。这样的事情(同样,确保$rootscope
$rootScope
):
angular.controller('appCtrl', function ($scope, $rootScope) {
var cleanUp = $rootScope.$on('channel.message', function () {
// do stuff here
};
cleanUp();
});
我遇到了同样的问题(多个回调被添加到队列中),上面的解决方案对我有用。
此外,这是偏离主题,但我可能会建议您按如下方式格式化控制器(仅建议):
angular.controller('appCtrl', ['$scope','$rootScope', function($scope, $rootScope) {
}]);
答案 1 :(得分:2)
由于@JoshBeam指出$ rootScope的返回值。$ on()是一个取消注册你的监听器的函数。他指出:
var cleanUp = $rootscope.$on('channel.message', function () {
// do stuff here
}
剩下的问题是何时触发清理。您很可能只想在销毁控制器时取消注册。令人高兴的是,在Angular撕下一个范围之前(例如,由于被破坏的控制器),它会在该特定范围内触发$destroy
event。因此,您可以使用以下命令触发清理。
$scope.$on('$destroy', function() {
cleanUp();
};
请注意,仅出于拆除目的,我们正在$destroy
上监听$scope
(而不是$rootScope
),以便在控制器拆除时收到消息。您可以将常规侦听器附加到$rootScope
。
另请注意,这也是用于防止内存泄漏的良好模式 - 即使您不担心多个侦听器。
答案 2 :(得分:1)
我建议按照我在这里的回答中所述创建一个$onRootScope
方法:
What's the correct way to communicate between controllers in AngularJS?
这会自动抽象出事件处理程序的注销,使用情况就像$scope.$onRootScope('fooEvent', function(){})
另请注意,最近版本的角度广播事件的性能影响不大。