1. 程式人生 > >angular中不同控制器之間的通訊方式

angular中不同控制器之間的通訊方式

在 Angular 中,Controller 之間通訊的方式主要有三種:

  1. 作用域繼承。利用子 Controller 控制父 Controller 上的資料。

  2. 注入服務。把需要共享的資料註冊為一個 service,在需要的 Controller 中注入。

  3. 基於事件。利用 Angular 的事件機制,使用 $on、$emit 和 $boardcast

一,作用域繼承 (僅適用於父子控制器之間)

html:

<div ng-controller="parentCtrl">
  <p>data in parent controller : {{data.name}}
</p> <div ng-controller="childCtrl"> <input type="text" ng-model="data.name"> </div> </div>

js:

angular.module('demo', [])

.controller('parentCtrl', ['$scope', function($scope){
    $scope.data = {
        name: 'htf'
    }
}])

.controller('childCtrl', ['$scope'
, function($scope){ }])

以上是父 Controller 中的資料是引用型別的情況。如果父 Controller 中的資料是基本型別,可通過 $scope.$parent.data 訪問。

二,定義一個 service (這種方式適用於任何需要通訊的 Controller 之間)

js:

angular.module('demo')
    .factory('Data', function(){
        return {
            name: 'htf'
        };
    })

html:

<div ng-controller
="childCtrl1">
<h3>data in child controller 1 :
{{data.name}}</h3> <input class="form-control" type="text" ng-model="data.name"> </div> <div ng-controller="childCtrl2"> <h3>data in child controller 2 : {{data.name}}</h3> <input class="form-control" type="text" ng-model="data.name"> </div>

js:

.controller('childCtrl1', ['$scope', 'Data', function($scope, Data){
    $scope.data = Data;
}])

.controller('childCtrl2', ['$scope', 'Data', function($scope, Data){
    $scope.data = Data;
}])

三,基於事件

Angular 為$scope 提供了冒泡和隧道機制,$broadcast 會把事件廣播給所有子 Controller,而 $emit 則會將事件冒泡傳遞給父 Controller,$on 則是 Angular 的事件監聽函式,利用這三者,可以實現上下級和同級(需要構造一個共同的父級 Controller)之間的通訊。

上下級之間:

如果是子 Controller 往父 Controller 上傳送事件(從作用域往上傳送事件),使用 scope.$emit

$scope.$emit("someEvent", {});

如果是父 Controller 往子 Controller 上傳送事件(從作用域往下發送事件),使用 scope.$broadcast

$scope.$broadcast("someEvent", {});

無論是 $emit 還是 $broadcast 傳送的事件,都用 $scope.$on 接收:

$scope.$on("someEvent", function(event, data) {
    // 這裡取到傳送過來的資料 data
});

同級之間:

同級之間利用事件通訊有兩種方法。一種是利用上下級之間事件傳播的變形,另一種是藉助 $rootScope

藉助父 controller:
在子 Controller 中向父 Controller 觸發一個事件,然後在父 Controller 中監聽事件,再廣播給子 Controller ,這樣通過事件攜帶的引數,實現了資料經過父 Controller,在同級 Controller 之間傳播。
但是要注意,通過父 Controller 作為中介進行傳遞的話,子 Controller 觸發的事件名和父 Controller 廣播用的事件名不能一樣,否則會進入死迴圈。

html:

<div ng-controller="outerCtrl">
  <h3>data in outer controller: {{name}}</h3>
  <div ng-controller="innerCtrl1">
    <input class="form-control" type="text" ng-model="name" ng-change="change()">
  </div>
  <div ng-controller="innerCtrl2">
    <input class="form-control" type="text" ng-model="name" ng-change="change()">
  </div>
</div>

js:

.controller('outerCtrl', ['$scope', function($scope){
    $scope.name = 'htf';
    $scope.$on('dataChanged', function(event, data){
        $scope.name = data;
        // 2. 父 Ctrl 監聽到 dataChanged 時間後,觸發 changeData 事件
        $scope.$broadcast('changeData', data);
    })
}])

.controller('innerCtrl1', ['$scope', function($scope){
    $scope.change = function(){
        // 1. 子 Ctrl1 中資料改變之後觸發 dataChanged 事件
        $scope.$emit('dataChanged', $scope.name);
    }
    $scope.$on('changeData', function(event, data){
        $scope.name = data;
    })
}])

.controller('innerCtrl2', ['$scope', function($scope){
    $scope.change = function(){
        $scope.$emit('dataChanged', $scope.name);
    }
    // 3. 監聽到 changeData 事件後,改變子 Ctrl2 中 資料
    $scope.$on('changeData', function(event, data){
        $scope.name = data;
    })
}])

藉助 $rootScope
每個 Angular 應用預設有一個根作用域\$rootScope, 根作用域位於最頂層,從它往下掛著各級作用域。

所以,如果子控制器直接使用 $rootScope 廣播和接收事件,那麼就可實現同級之間的通訊。
html:

<div ng-controller="innerCtrlA">
    <input class="form-control" type="text" ng-model="name" ng-change="change()">
</div>
<div ng-controller="innerCtrlB">
    <input class="form-control" type="text" ng-model="name" ng-change="change()">
</div>

js:

.controller('innerCtrlA', ['$scope', '$rootScope', function($scope, $rootScope){
    $scope.change = function(){
        // 廣播事件
        $rootScope.$broadcast('nameChanged', $scope.name);
    }
    $rootScope.$on('nameChanged', function(event, data){
        $scope.name = data;
    })
}])

.controller('innerCtrlB', ['$scope', '$rootScope', function($scope, $rootScope){
    $scope.change = function(){
        $rootScope.$broadcast('nameChanged', $scope.name);
    }
    // 監聽事件
    $rootScope.$on('nameChanged', function(event, data){
        $scope.name = data;
    })
}])