1. 程式人生 > >AngularJS控制器controller如何通訊?

AngularJS控制器controller如何通訊?

本文轉自https://segmentfault.com/a/1190000000639592點選開啟連結

關於控制器如何通訊的問題,是不少剛接觸angulr的同學想知道的。總的來說,angular控制器通訊的方式有三種:
1,利用作用域繼承的方式。即子控制器繼承父控制器中的內容

2,基於事件的方式。即$on,$emit,$boardcast這三種方式

3,服務方式。寫一個服務的單例然後通過注入來使用

利用作用域的繼承方式

由於作用域的繼承是基於js的原型繼承方式,所以這裡分為兩種情況,當作用域上面的值為基本型別的時候,修改父作用域上面的值會
影響到子作用域,反之,修改子作用域只會影響子作用域的值,不會影響父作用域上面的值;如果需要父作用域與子作用域共享一個值
的話,就需要用到後面一種,即作用域上的值為物件,任何一方的修改都能影響另一方,這是因為在js中物件都是引用型別。

基本型別

    function Sandcrawler($scope) {
    $scope.location = "Mos Eisley North";
    $scope.move = function(newLocation) {
        $scope.location = newLocation;
    }
};
function Droid($scope) {
    $scope.sell = function(newLocation) {
        $scope.location = newLocation;
    }
}

// html

    <div
ng-controller="Sandcrawler">
<p>Location: </p> <button ng-click="move('Mos Eisley South')">Move</button> <div ng-controller="Droid"> <p>Location: </p> <button ng-click="sell('Owen Farm')">Sell</button> </div> </div
>

物件

    function Sandcrawler($scope) {
    $scope.obj = {location:"Mos Eisley North"};
}
function Droid($scope) {
    $scope.summon = function(newLocation) {
        $scope.obj.location = newLocation;
    }
}

// html

    <div ng-controller="Sandcrawler">
    <p>Sandcrawler Location: </p>
    <div ng-controller="Droid">
        <button ng-click="summon('Owen Farm')">
            Summon Sandcrawler
        </button>
    </div>
</div>

基於事件的方式

在一般情況下基於繼承的方式已經足夠滿足大部分情況了,但是這種方式沒有實現兄弟控制器之間的通訊方式,所以引出了事件的方式
。基於事件的方式中我們可以裡面作用的$on,$emit,$boardcast這幾個方式來實現,其中$on表示事件監聽,$emit表示向父級以上的
作用域觸發事件, $boardcast表示向子級以下的作用域廣播事件。參照以下程式碼:

向上傳播事件

    function Sandcrawler($scope) {
    $scope.location = "Mos Eisley North";
    $scope.$on('summon', function(e, newLocation) {
        $scope.location = newLocation;
    });
}
function Droid($scope) {
    $scope.location = "Owen Farm";
    $scope.summon = function() {
        $scope.$emit('summon', $scope.location);
    }
}

// html

    <div ng-controller="Sandcrawler">
    <p>Sandcrawler Location: </p>
    <div ng-controller="Droid">
        <p>Droid Location: </p>
        <button ng-click="summon()">Summon Sandcrawler</button>
    </div>
</div>

向下廣播事件

    function Sandcrawler($scope) {
    $scope.location = "Mos Eisley North";
    $scope.recall = function() {
        $scope.$broadcast('recall', $scope.location);
    }
}
function Droid($scope) {
    $scope.location = "Owen Farm";
    $scope.$on('recall', function(e, newLocation) {
        $scope.location = newLocation;
    });
}

//html

    <div ng-controller="Sandcrawler">
    <p>Sandcrawler Location: </p>
    <button ng-click="recall()">Recall Droids</button>
    <div ng-controller="Droid">
        <p>Droid Location: </p>
    </div>
</div>

從這個用法我們可以引申出一種用於兄弟控制間進行通訊的方法,首先我們一個兄弟控制中向父作用域觸發一個事件,然後在父作用域
中監聽事件,再廣播給子作用域,這樣通過事件攜帶的引數,實現了資料經過父作用域,在兄弟作用域之間傳播。這裡要注意的是,通過父元素作為中介進行傳遞的話,兄弟元素用的事件名不能一樣,否則會進入死迴圈。請看程式碼:

-兄弟作用域之間傳播

    function Sandcrawler($scope) {
    $scope.$on('requestDroidRecall', function(e) {
        $scope.$broadcast('executeDroidRecall');
    });
}
function Droid($scope) {
    $scope.location = "Owen Farm";
    $scope.recallAllDroids = function() {
        $scope.$emit('requestDroidRecall');
    }
    $scope.$on('executeDroidRecall', function() { 
        $scope.location = "Sandcrawler"
    });
}

// html

    <div ng-controller="Sandcrawler">
    <div ng-controller="Droid">
        <h2>R2-D2</h2>
        <p>Droid Location: </p>
        <button ng-click="recallAddDroids()">Recall All Droids</button>
    </div>
    <div ng-controller="Droid">
        <h2>C-3PO</h2>
        <p>Droid Location: </p>
        <button ng-click="recallAddDroids()">Recall All Droids</button>
    </div>
</div>

angular服務的方式

在ng中服務是一個單例,所以在服務中生成一個物件,該物件就可以利用依賴注入的方式在所有的控制器中共享。參照以下例子,在一個控制器修改了服務物件的值,在另一個控制器中獲取到修改後的值:

   var app = angular.module('myApp', []);
app.factory('instance', function(){
    return {};
});
app.controller('MainCtrl', function($scope, instance) {
  $scope.change = function() {
       instance.name = $scope.test;
  };
});
app.controller('sideCtrl', function($scope, instance) {
    $scope.add = function() {
        $scope.name = instance.name;
    };
});

//html

    <div ng-controller="MainCtrl">
     <input type="text" ng-model="test" />
     <div ng-click="change()">click me</div>
</div>
<div ng-controller="sideCtrl">
    <div ng-click="add()">my name </div>
</div>