1. 程式人生 > >使用angularjs1.x構建前臺開發框架(十一)——資料雙向繫結

使用angularjs1.x構建前臺開發框架(十一)——資料雙向繫結

angularjs中有兩個非常重要的概念,一個就是本章要介紹的資料雙向繫結,另一個則是從後端延伸過來的依賴注入。那麼何為資料雙向繫結呢?顧名思義,即元資料(model)和檢視(view)展示的資料存在繫結關係,當元資料中的資訊發生變化時,檢視中的資料會實時變化,反之亦然。

首先我們來看一個檢視資料變更對映到元資料中的例子:

首先在controller中定義一個變數data,然後在頁面上定義的輸入框繫結這個變數,接下來在輸入框中改變這個變數的值,最後通過在controller中定義的定時器來檢視變數是否隨著檢視中的變更而變化。

在c2.js中定義變數以及定時器:

/**
 * Created by 李慶 on 2016/10/6.
 */
define(["jquery","../../../framework/service/httpService"],function($,httpService){
    var c2Controller = ["$scope","maskService",function($scope,maskService){
        $scope.test = function(){
            console.log("enter controller");
        };

        $scope.getData = function(){
            maskService.show("get data");
            $.ajax({
                "type":"GET",
                "contentType":"application/json;charset=UTF-8",
                //修改前為"url":"mock/test.json",
                "url":httpService.getUrl("GET","/nova/test.json"),
                "success":function(data){
                    console.log(JSON.stringify(data));
                    setTimeout(function(){
                        maskService.hide();
                    },6000);
                },
                "error":function(data){
                    console.log("error");
                }
            });
        };

        $scope.data = "";
        setInterval(show,1000);


        function show(){
            console.log("data is "+ $scope.data);
        }
    }];
    return c2Controller;
});

變更部分內容如下:


在c2.html中定義輸入框並繫結controller中定義的變數:

<div>
    <input ng-model="data" value="">
    <input type="button" value="test Controller" ng-click="test()">
    <button ng-click="getData()">request</button>
</div>

變更部分內容如下:


然後我們來看一下頁面:


在沒有改變輸入框的值之前,定時器列印的data變數值一直為空,當在輸入框中輸入1後,定時器列印的data變數值變為1,這表示檢視資料變更對映到了元資料。

上面的例子中,controller中定義的變數data在頁面上定義的輸入框中正常顯示,即為元資料對映到了檢視,接下來我們看一個元資料對映到檢視的特例:

我們在上例的定時器中變更變數data的值,檢視輸入框的值是否同步變更。

在c2.js中定義變數以及定時器:

/**
 * Created by 李慶 on 2016/10/6.
 */
define(["jquery","../../../framework/service/httpService"],function($,httpService){
    var c2Controller = ["$scope","maskService",function($scope,maskService){
        $scope.test = function(){
            console.log("enter controller");
        };

        $scope.getData = function(){
            maskService.show("get data");
            $.ajax({
                "type":"GET",
                "contentType":"application/json;charset=UTF-8",
                //修改前為"url":"mock/test.json",
                "url":httpService.getUrl("GET","/nova/test.json"),
                "success":function(data){
                    console.log(JSON.stringify(data));
                    setTimeout(function(){
                        maskService.hide();
                    },6000);
                },
                "error":function(data){
                    console.log("error");
                }
            });
        };

        $scope.data = 0;
        console.log(new Date());
        setInterval(show,1000);

        function show(){
            console.log(new Date());
            $scope.data++;
            console.log("data is "+ $scope.data);
        }
    }];
    return c2Controller;
});

變更部分內容如下(這裡為了方便檢視資料變化,還列印了時間戳):


c2.html內容不變。

然後我們來看一下頁面:


可以看到控制檯列印的變數一直在變更,但是輸入框的值一直保持不變。為什麼資料雙向繫結在這裡失效了呢?這是由於我們在controller中自定義的定時器變更變數的行為angularjs並不感知(類似的行為還包括ajax的非同步請求),此時就需要靠我們來主動觸發資料雙向繫結:

在c2.js中定義變數以及定時器,並主動觸發資料雙向繫結:

/**
 * Created by 李慶 on 2016/10/6.
 */
define(["jquery","../../../framework/service/httpService"],function($,httpService){
    var c2Controller = ["$scope","maskService",function($scope,maskService){
        $scope.test = function(){
            console.log("enter controller");
        };

        $scope.getData = function(){
            maskService.show("get data");
            $.ajax({
                "type":"GET",
                "contentType":"application/json;charset=UTF-8",
                //修改前為"url":"mock/test.json",
                "url":httpService.getUrl("GET","/nova/test.json"),
                "success":function(data){
                    console.log(JSON.stringify(data));
                    setTimeout(function(){
                        maskService.hide();
                    },6000);
                },
                "error":function(data){
                    console.log("error");
                }
            });
        };

        $scope.data = 0;
        console.log(new Date());
        setInterval(show,1000);

        function show(){
            console.log(new Date());
            $scope.$apply(function($scope){
                $scope.data++;
            });
            console.log("data is "+ $scope.data);
        }
    }];
    return c2Controller;
});

變更部分內容如下:


c2.html保持不變。

再看一下此時的頁面:


此時控制檯列印的變數一直在變更,且輸入框的值也保持同步變更。

注意,只有在以下幾種情況下才會觸發資料雙向繫結:

ng標籤觸發的事件

angularjs服務觸發的資料變更(如$inerval,而不是原生的setInterval函式)

主動執行$digest()或$apply()