각도로 $ on 및 $ broadcast


282

다른 뷰가있는 footerController와 codeScannerController가 있습니다.

angular.module('myApp').controller('footerController', ["$scope", function($scope) {}]);

angular.module('myApp').controller('codeScannerController', ["$scope", function($scope) {
console.log("start");
$scope.startScanner = function(){...

<li>footer.html을 클릭하면 codeScannerController에서이 이벤트를 가져와야합니다.

<li class="button" ng-click="startScanner()">3</li>

나는 그것이 실현 될 수 있다고 생각 $on하고 $broadcast있지만, 난 아무데도 예를 찾을 수 없습니다 어떻게 모른다.

답변:


631

당신이 $broadcast사용하려면 $rootScope:

$scope.startScanner = function() {

    $rootScope.$broadcast('scanner-started');
}

그런 다음 $scope컨트롤러 의 를 사용하십시오 .

$scope.$on('scanner-started', function(event, args) {

    // do what you want to do
});

원하는 경우 다음과 같은 경우 인수를 전달할 수 있습니다 $broadcast.

$rootScope.$broadcast('scanner-started', { any: {} });

그리고 그것들을 받으십시오 :

$scope.$on('scanner-started', function(event, args) {

    var anyThing = args.any;
    // do what you want to do
});

Scope 문서 내부에 대한 설명서입니다 .


2
원하는대로 이벤트 이름을 지정할 수 있습니다.
Davin Tryon

5
$ scope. $ apply ();인지 확인하십시오. 당신의 변화!
Ismail

4
@Ismail 왜 ... 어디서?
Jaans

7
브로드 캐스트 메시지를 하드 코딩하는 대신 이러한 문자열을 저장하는 권장 방법이 있습니까?
rperryng

8
@Ismail $scope.$apply()은 각도 프레임 워크 외부에서 모델을 변경할 때만 필요합니다 (setTimeout, 대화 상자 콜백 또는 ajax 콜백과 같이). 즉, $apply()모든 코드 입력 .$on()이 완료된 후에 이미 트리거 됩니다.
th3uiguy 2016 년

97

먼저, 간단한 설명 $on(), $broadcast()$emit() :

  • .$on(name, listener) -주어진 특정 이벤트를 청취 name
  • .$broadcast(name, args)- $scope모든 어린이를 통해 이벤트를 방송
  • .$emit(name, args)- $scope계층을 포함한 모든 부모에게 이벤트를$rootScope

다음 HTML을 기반으로합니다 ( 여기에서 전체 예제 참조 ).

<div ng-controller="Controller1">
    <button ng-click="broadcast()">Broadcast 1</button>
    <button ng-click="emit()">Emit 1</button>
</div>

<div ng-controller="Controller2">
    <button ng-click="broadcast()">Broadcast 2</button>
    <button ng-click="emit()">Emit 2</button>
    <div ng-controller="Controller3">
        <button ng-click="broadcast()">Broadcast 3</button>
        <button ng-click="emit()">Emit 3</button>
        <br>
        <button ng-click="broadcastRoot()">Broadcast Root</button>
        <button ng-click="emitRoot()">Emit Root</button>
    </div>
</div>

시작된 이벤트는 $scopes다음과 같이 진행됩니다.

  • 브로드 캐스트 1-컨트롤러 1 만 볼 수 있습니다 $scope
  • 방출 1 - 컨트롤러 1 볼 수 있을까요 $scope다음$rootScope
  • 브로드 캐스트 2-컨트롤러 2에 표시되고 $scope컨트롤러 3에 표시됩니다.$scope
  • 방출 2 - 컨트롤러 2 볼 수 있을까요 $scope다음$rootScope
  • 브로드 캐스트 3-컨트롤러 3 만 볼 수 있습니다 $scope
  • 방출 3 - 제어기 (3) 볼 수 있을까요 $scope, 컨트롤러 2 $scope다음$rootScope
  • 방송 루트 - 볼 수 있을까요 $rootScope$scope(다음 1 3 2) 모든 컨트롤러의
  • 뿌리 방출-만 볼 수 있습니다 $rootScope

이벤트를 트리거하는 JavaScript (다시, 여기 에서 실제 예제를 볼 수 있음 ) :

app.controller('Controller1', ['$scope', '$rootScope', function($scope, $rootScope){
    $scope.broadcastAndEmit = function(){
        // This will be seen by Controller 1 $scope and all children $scopes 
        $scope.$broadcast('eventX', {data: '$scope.broadcast'});

        // Because this event is fired as an emit (goes up) on the $rootScope,
        // only the $rootScope will see it
        $rootScope.$emit('eventX', {data: '$rootScope.emit'});
    };
    $scope.emit = function(){
        // Controller 1 $scope, and all parent $scopes (including $rootScope) 
        // will see this event
        $scope.$emit('eventX', {data: '$scope.emit'});
    };

    $scope.$on('eventX', function(ev, args){
        console.log('eventX found on Controller1 $scope');
    });
    $rootScope.$on('eventX', function(ev, args){
        console.log('eventX found on $rootScope');
    });
}]);

당신이 제시 한 예제로 내 앱의 계층 구조를 어떻게 상상할 수 있습니까? 컨트롤러는 어떻게 부모 또는 자식이 될 수 있습니까 ??? 내가 말하려는 것은 일련의 상태를 가지고 있다는 것입니다. LoginCtrl-> homeCrl-> notificationCtrl 등.
HIRA THAKUR

26

한 가지 알아야 할 것은 $ 접두사는 Angular Method를, $$ 접두사는 사용을 피해야하는 Angular Method를 나타냅니다.

아래는 예제 템플릿과 해당 컨트롤러입니다. $ broadcast / $ on이 원하는 것을 달성하는 데 어떻게 도움이되는지 살펴 보겠습니다.

<div ng-controller="FirstCtrl">
    <input ng-model="name"/> 
    <button ng-click="register()">Register </button>
</div>

<div ng-controller="SecondCtrl">
    Registered Name: <input ng-model="name"/> 
</div>

컨트롤러는

app.controller('FirstCtrl', function($scope){
    $scope.register = function(){

    }
});

app.controller('SecondCtrl', function($scope){

});

내 질문은 사용자가 등록을 클릭 할 때 이름을 두 번째 컨트롤러에 어떻게 전달합니까? 여러 솔루션을 생각해 낼 수 있지만 우리가 사용할 솔루션은 $ broadcast 및 $ on을 사용하는 것입니다.

브로드 캐스트 대 $ emit

우리는 어느 것을 사용해야합니까? $ broadcast는 모든 자식 dom 요소로 전달되고 $ emit은 모든 조상 dom 요소와 반대 방향으로 전달됩니다.

$ emit 또는 $ broadcast를 결정하지 않는 가장 좋은 방법은 $ rootScope에서 채널을 만들고 $ broadcast를 모든 자식에게 사용하는 것입니다. dom 요소가 형제이기 때문에 우리의 경우를 훨씬 쉽게 만듭니다.

$ rootScope 추가 및 $ broadcast 가능

app.controller('FirstCtrl', function($rootScope, $scope){
    $scope.register = function(){
        $rootScope.$broadcast('BOOM!', $scope.name)
    }
});

$ rootScope를 추가했고 이제 $ broadcast (broadcastName, arguments)를 사용하고 있습니다. broadcastName의 경우 고유 한 이름을 지정하여 secondCtrl에서 해당 이름을 찾을 수 있습니다. BOOM을 선택했습니다! 재미로. 두 번째 인수 '인수'는 값을 리스너에게 전달할 수있게합니다.

방송 받기

두 번째 컨트롤러에서는 방송을 들으려면 코드를 설정해야합니다

app.controller('SecondCtrl', function($scope){
  $scope.$on('BOOM!', function(events, args){
    console.log(args);
    $scope.name = args; //now we've registered!
  })
});

정말 간단합니다. 라이브 예

비슷한 결과를 얻는 다른 방법

이 방법을 사용하는 것은 비효율적이거나 유지하기 쉽지 않지만 문제를 해결하는 간단한 방법이므로 사용하지 마십시오.

일반적으로 서비스를 사용하거나 컨트롤러를 단순화하여 동일한 작업을 수행 할 수 있습니다. 우리는 이것에 대해 자세히 논의하지는 않지만 완전성을 위해 언급하겠다고 생각했습니다.

마지막으로, '$ destroy'를 들으려면 정말 유용한 브로드 캐스트를 다시 명심하십시오. $는 벤더 코드에 의해 생성 된 메소드 또는 객체임을 의미합니다. 어쨌든 $ destroy는 컨트롤러가 파괴 될 때 브로드 캐스팅됩니다. 컨트롤러를 제거 할 때이 정보를 듣고 싶을 수 있습니다.


2
경고로 앱에서 너무 많은 브로드 캐스트 / 이미 트를 사용하지 마십시오. 이러한 이벤트의 근본을 추적하는 것은 매우 어려운 작업이므로 특히 큰 앱에서 관리하기가 매우 어려울 수 있습니다.
Yang Li

1
//Your broadcast in service

(function () { 
    angular.module('appModule').factory('AppService', function ($rootScope, $timeout) {

    function refreshData() {  
        $timeout(function() {         
            $rootScope.$broadcast('refreshData');
        }, 0, true);      
    }

    return {           
        RefreshData: refreshData
    };
}); }());

//Controller Implementation
 (function () {
    angular.module('appModule').controller('AppController', function ($rootScope, $scope, $timeout, AppService) {            

       //Removes Listeners before adding them 
       //This line will solve the problem for multiple broadcast call                             
       $scope.$$listeners['refreshData'] = [];

       $scope.$on('refreshData', function() {                                                    
          $scope.showData();             
       });

       $scope.onSaveDataComplete = function() { 
         AppService.RefreshData();
       };
    }); }());
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.