질문 : 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
이제 등록되지 않은 범위에 대한 버블 링을 방지하고 $ emit만큼 빠르게 실행됩니다.
이제 다음을 수행 할 수 있습니다.
$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
에서 발생하는 이벤트를 구독 $scope
가 파괴 될 때 처리기를 직접 $rootScope
$onRootScope
메서드를 제공하기 위해 $rootScope
를 원숭이 패치하는 가장 깨끗한 방법은 데코레이터를 사용하는 것입니다 (실행 블록도 잘 수행 할 수 있지만 pssst, 아무에게도 말하지 마십시오).
$scope
$onRootScope
속성이 예기치 않게 표시되지 않도록하기 위해 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
$broadcast
$scope
사용하여 적절한 시나리오에서 테이블에 미치는 성능 영향을 보여주는 jsperf입니다.
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
출처 : https://stackoverflow.com/questions/11252780/whats-the-correct-way-to-communicate-between-controllers-in-angularjs
'프로그래밍 언어 > HTML,CSS,JS' 카테고리의 다른 글
AngularJS의 지시문 범위에서 '@' 와 '=' 의 차이점 (0) | 2021.09.28 |
---|---|
Node.js로 명령 줄 바이너리 실행 하는 방법 (0) | 2021.09.27 |
JavaScript에서 숫자를 문자열로 변환하는 가장 좋은 방법 (0) | 2021.09.27 |
CSS를 사용하여 페이지 로드시 페이드 인 효과 내기 (0) | 2021.09.27 |
CSS text-overflow: ellipsis; 가 작동하지 않을 때 (0) | 2021.09.27 |