使用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()