angular controller之間通信方式


  對於日常開發中,難免會有controller之間通信需求。對於controller之間通信有兩種方式可以做到。

用 Angular 進行開發,基本上都會遇到 Controller 之間通信的問題,本文對此進行一個總結。

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

1)作用域繼承。利用子 Controller 控制父 Controller 上的數據。(父 Controller 中的數據要為引用類型,不能是基本類型,原因參見 AngularJS中的作用域 一文)

2)注入服務。把需要共享的數據注冊為一個 service,在需要的 Controller 中注入。

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

其中,作用域繼承僅限於上下級之間的通信,注入服務和基於事件的機制可以實現任意級別的 Controller 通信。

在 這里 可以查看下面栗子的演示。

作用域繼承

原理在 作用域 一文中有講解,這里直接上栗子。

頁面:

<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>

控制器:

angular.module('demo', [])

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

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

}])

 

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

很顯然,這種方式僅適用於父子級間 Controller 的通信。

注入服務

在 Angular 中,服務是一個單例,所以在服務中生成一個對象,該對象就可以利用依賴注入的方式在所有的控制器中共享。

看個栗子,先定義一個 service :

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

 

頁面:

<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>

 

控制器:

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

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

 

這種方式適用於任何需要通信的 Controller 之間。

基於事件

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 廣播用的事件名不能一樣,否則會進入死循環。

看代碼:

<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>

 

關鍵部分在控制器:

.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 廣播和接收事件,那么就可實現同級之間的通信。

看栗子:

<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>

 

控制器:

.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;
    })
}])

 

參考

  1. 作用域與事件
  2. Angularjs Controller 間通信機制
  3. Communicating Between Controllers In Angular
  4. AngularJS控制器controller如何通信?
  5. controller 間共享數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM