AngularJS中控制器之间的正确通信方式是什么?
控制器之间通信的正确方式是什么?
我目前正在使用涉及window
的可怕软糖:
function StockSubgroupCtrl($scope, $http) {
$scope.subgroups = [];
$scope.handleSubgroupsLoaded = function(data, status) {
$scope.subgroups = data;
}
$scope.fetch = function(prod_grp) {
$http.get('/api/stock/groups/' + prod_grp + '/subgroups/').success($scope.handleSubgroupsLoaded);
}
window.fetchStockSubgroups = $scope.fetch;
}
function StockGroupCtrl($scope, $http) {
...
$scope.select = function(prod_grp) {
$scope.selectedGroup = prod_grp;
window.fetchStockSubgroups(prod_grp);
}
}
编辑 :在这个答案中解决的问题已在angular.js版本1.2.7中解决。 $broadcast
现在避免了在未注册的范围上冒泡,运行速度与$发射一样快。
所以,现在你可以:
$rootScope
$broadcast
$scope
中的$on
监听 下面的原始答案
我强烈建议不要使用$rootScope.$broadcast
+ $scope.$on
,而是使用$rootScope.$emit
+ $rootScope.$on
。 前者可能会导致@numan引发的严重性能问题。 这是因为这个事件会在所有范围内都会发生。
然而,后者(使用$rootScope.$emit
+ $rootScope.$on
) 不会从该遭受并且因此可以被用作快速通信信道!
从$emit
的角度文档:
通过范围层次向上调度事件名称,通知注册
由于在$rootScope
之上没有作用域,因此不会冒泡。 使用$rootScope.$emit()
/ $rootScope.$on()
作为EventBus是完全安全的。
但是,从控制器内部使用它时有一个问题。 如果直接绑定到控制器内的$rootScope.$on()
,则必须在本地$scope
被销毁时自行清理绑定。 这是因为控制器(与服务相反)可以在应用程序的整个生命周期中多次实例化,这会导致绑定总结,最终在各处产生内存泄漏:)
要取消注册,只需监听$scope
的$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
,该$onRootScope
订阅$rootScope
上发出的事件,但也会在本地$scope
被销毁时直接清除处理程序。
猴子修补$rootScope
以提供这种$onRootScope
方法的最$onRootScope
方法是通过一个装饰器(一个运行块可能会做得很好,但是pssst,不要告诉任何人)
为了确保枚举$scope
$onRootScope
属性不会出现意外,我们使用Object.defineProperty()
并将enumerable
设置为false
。 请记住,您可能需要一个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;
}]);
}]);
使用这种方法,上面的控制器代码可以简化为:
angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);
因此,作为所有这些的最终结果,我强烈建议您使用$rootScope.$emit
+ $scope.$onRootScope
。
顺便说一句,我试图说服角度团队解决角内核问题。 这里有一个讨论:https://github.com/angular/angular.js/issues/4574
下面是一个jsperf,它显示了$broadcast
$scope
的正常情况下$broadcast
带来的影响。
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
这里最好的答案是从@ozmalifeguard已经提到的角度问题中解决(至少在版本> 1.2.16和“可能更早的版本”)。 但是我没有一个真正的解决方案,而只是阅读所有这些答案
在我看来,现在的答案应该是
$rootScope
$broadcast
$scope
中的$on
监听 因此发布
// EXAMPLE PUBLISHER
angular.module('test').controller('CtrlPublish', ['$rootScope', '$scope',
function ($rootScope, $scope) {
$rootScope.$broadcast('topic', 'message');
}]);
并订阅
// EXAMPLE SUBSCRIBER
angular.module('test').controller('ctrlSubscribe', ['$scope',
function ($scope) {
$scope.$on('topic', function (event, arg) {
$scope.receiver = 'got your ' + arg;
});
}]);
Plunkers
Controller As
语法 如果将监听器注册到本地$scope
,则在关联的控制器被删除时,它将被$destroy
本身自动$destroy
。
对于PubSub通信,使用$ rootScope。$ broadcast和$ scope。$ on。
另外,请看这篇文章:AngularJS - 在控制器之间进行通信
链接地址: http://www.djcxy.com/p/77599.html上一篇: What's the correct way to communicate between controllers in AngularJS?