AngularJS(三)——在多個AngularJS controller之間共享數據


MVC中,爲了方便維護,針對不同業務會使用不同的controller。有時我們需要在不同的controller中共享數據,本文旨在解決這一問題。

1. 使用$rootScope直接綁定

AngularJS中有一個$rootScope對象,它是AngularJS中最接近全局作用域的對象,是所有$scope對象的最上層,可以簡單理解爲BOM中的window對象或Node.js中的global對象。最簡單的方式是直接將要共享的數據綁定到$rootScope對象中:

<!DOCTYPE html>
<html ng-app="exampleApp">
<head>
    <meta charset="utf-8">
    <title>Share Between Ctrls</title>
    <script src="lib/angular.js"></script>
    <link href="css/bootstrap.min.css" rel="stylesheet" />
    <link rel="stylesheet" href="css/bootstrap-responsive.min.css">
    <script>
        var app = angular.module("exampleApp", []);
        app.controller("FirstController", function($rootScope, $scope) {
            $scope.shareObject = function (obj) {
                $rootScope.person = obj || {};
            };
        });

        app.controller("SecondController", function($rootScope, $scope) {
            $scope.reportData = function() {
                var reportString = "",
                    person = $rootScope.person || {};
                for(var i in person) {
                    reportString += "person's " + i + " is " + person[i] + "\n";
                }
                alert(reportString);
            };
        });
    </script>
</head>
<body>
    <div class="well" ng-controller="FirstController">
        <input type="text" ng-model="person.name" placeholder="Input Your Name" />
        <input type="text" ng-model="person.age" placeholder="Input Your Age" />
        <input type="text" ng-model="person.sex" placeholder="Input Your Sex" />
        <button class="btn btn-primary" ng-click="shareObject(person)">Share Data</button>
    </div>
    <div class="well" ng-controller="SecondController">
        <button class="btn btn-primary" ng-click="reportData()">Report Data</button>
    </div>
</body>
</html>

整個效果如圖-1 ~ 圖-4所示:

圖-1

圖-1 頁面加載完畢

圖-2

圖-2 第一次點擊"Report Data"按鈕

圖-3

圖-3 填寫信息,點擊"Share Data"按鈕

圖-4

圖-4 再次點擊"Report Data"按鈕

這樣做解決了問題,在需要共享的數據量較少時可以採用,但因爲會污染全局作用域,因此十分不推薦使用這種方法。

2. 使用service共享數據

...
<script>
    var app = angular.module("exampleApp", []);
    //需要將DataShareService注入
    app.controller("FirstController", function($scope, DataShareService) {
        $scope.person = {};
        $scope.shareObject = function (obj) {
            //賦值
            DataShareService.shareObject = obj;
        };
    });

    //需要將DataShareService注入
    app.controller("SecondController", function($scope, DataShareService) {
        var person = {};
        $scope.reportData = function() {
            var reportString = "",
                person = DataShareService.shareObject; //取值
            for(var i in person) {
                reportString += "person's " + i + " is " + person[i] + "\n";
            }
            alert(reportString);
        };
    });

    //自定義service,在多個controller之間共享數據
    app.service("DataShareService", function() {
        //無需定義其他變量,無需return,如果使用factory()則至少需要return一個空對象
    });
    <!-- 
         這裏的
         app.factory()
         可以替換爲
         app.constant()
         app.value()
         app.service()
     -->
</script>
...

最終實現的效果和使用$rootScope直接綁定完全相同,優點是解決了全局作用域被污染問題。有關最後app.factory()的替換問題可以參考之前的一篇博客,使用AngularJS自定義service,有興趣的讀者可以自己試驗一下。

3. 使用$scope事件機制

$scope可以向其他$scope廣播或發送事件,其他$scope監聽事件並處理,從而實現通信,也就是說可以通過$scope事件機制實現不同controller之間的數據共享。$scope事件機制包括以下三種方法:

wKiom1XMaynD8ixyAAEkufmDtMQ207.jpg

表-1 有關$scope事件機制的三個方法

其中,$broadcast(name, args)爲父級$scope向子級$scope發送事件,$emit(name, args)爲子級$scope向父級$scope發送事件,$on(name, handler)爲監聽事件的函數,handler參數爲對事件進行處理的函數,該函數包含兩個參數:event和args,分別爲事件對象和發送事件時傳遞的args參數。

這裏我們不存在controller的嵌套,所有的$scope爲同級,需要使用“祖宗級”$rootScope進行廣播。有關controller嵌套和繼承的問題會在之後的博文中講到。

使用$scope事件機制處理數據共享的JS代碼如下所示,由於HTML代碼與之前相同,故省略:

...
<script>
    var app = angular.module("exampleApp", []);
    app.controller("FirstController", function($rootScope, $scope) {
        $scope.person = {};
        $scope.shareObject = function (obj) {
            obj = obj || {};
            //將事件以"ShareObjectEvent"爲名進行廣播
            $rootScope.$broadcast("ShareObjectEvent", obj);
        };
    });

    app.controller("SecondController", function($scope) {
        //監聽"ShareObjectEvent"事件
        $scope.$on("ShareObjectEvent", function(event, args) {
            person = args;
        });
        $scope.reportData = function() {
            var reportString = "";
            for(var i in person) {
                reportString += "person's " + i + " is " + person[i] + "\n";
            }
            alert(reportString);
        };
    });
</script>
...

最終實現的效果和使用$rootScope直接綁定完全相同。

最後需要補充的一點是,使用$scope事件機制與前兩種方法相比有着實時性的優勢,即數據的變化能夠及時被響應,如果想在使用前兩種方法時達到監聽數據變化實時響應的效果,需要用到AngularJS的$watch$watchCollection功能,詳情請參考這裏

完。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章