雙向數(shù)據(jù)綁定指的是兩個(gè)方向,這兩個(gè)方向指的是從視圖到數(shù)據(jù)模型,AngularJS是MVC框架,程序主要是通過控制器進(jìn)行操作的,控制器去修改數(shù)據(jù)模型,數(shù)據(jù)模型的變更會(huì)反應(yīng)到視圖上。視圖上面如果發(fā)生了數(shù)據(jù)變化AngularJS框架會(huì)同步到數(shù)據(jù)模型中。
簡單例子
<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-controller="HelloAngular">
<p>{{greeting.text}},Angular</p>
</div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script src="HelloAngular_MVC.js"></script>
</html>
function HelloAngular($scope) {
$scope.greeting = {
text: 'Hello'
};
}
html頁面中p標(biāo)簽的雙花口號(hào)是一個(gè)取值表達(dá)式,
這個(gè)頁面有一個(gè)問題,如果刷新頁面在網(wǎng)絡(luò)不好的情況下可能會(huì)看到{{greeting.text}}
取值表達(dá)式與ng-bind指令
AngularJS提供了一個(gè)叫ng-bind指令來避免上面出現(xiàn)取值表達(dá)式的問題,
<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-controller="HelloAngular">
<p><span ng-bind="greeting.text"></span>,Angular</p>
</div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script src="HelloAngular_MVC.js"></script>
</html>
function HelloAngular($scope) {
$scope.greeting = {
text: 'Hello'
};
}
使用ng-bind指令不會(huì)出現(xiàn)取值表達(dá)式的問題
在{{}}取值表達(dá)式和ng-bind間如何取舍,什么時(shí)候該使用哪個(gè)呢?
AngularJS本身的庫在記載完以后整個(gè)頁面就歸AngularJS來管了這個(gè)時(shí)候使用{{}}綁定的方式呢就不會(huì)有很大的問題。
也就是說在應(yīng)用主程序index中如果有數(shù)據(jù)綁定,使用ng-bind去綁定,一般在導(dǎo)入ng核心庫的時(shí)候一般都是放在index上面,一般不會(huì)在內(nèi)層去加載ng核心庫,所以后續(xù)的頁面通過模板加載進(jìn)來的頁面使用{{}}綁定就ok了。這樣是不會(huì)堪當(dāng)表達(dá)式的。
在什么情況下會(huì)需要視圖會(huì)修改值,然后導(dǎo)致去改變數(shù)據(jù)模型呢?
典型的場景就是form表單,form是讓用戶可以交互和輸入的。
雙向綁定的經(jīng)典場景
<!doctype html>
<html ng-app="UserInfoModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap-3.0.0/css/bootstrap.css">
<script src="js/angular-1.3.0.js"></script>
<script src="Form.js"></script>
</head>
<body>
<div class="panel panel-primary">
<div class="panel-heading">
<div class="panel-title">雙向數(shù)據(jù)綁定</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<form class="form-horizontal" role="form" ng-controller="UserInfoCtrl">
<div class="form-group">
<label class="col-md-2 control-label">
郵箱:
</label>
<div class="col-md-10">
<input type="email" class="form-control" placeholder="推薦使用126郵箱" ng-model="userInfo.email">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">
密碼:
</label>
<div class="col-md-10">
<input type="password" class="form-control" placeholder="只能是數(shù)字、字母、下劃線" ng-model="userInfo.password">
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="userInfo.autoLogin">自動(dòng)登錄
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button class="btn btn-default" ng-click="getFormData()">獲取Form表單的值</button>
<button class="btn btn-default" ng-click="setFormData()">設(shè)置Form表單的值</button>
<button class="btn btn-default" ng-click="resetForm()">重置表單</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
var userInfoModule = angular.module('UserInfoModule', []);
userInfoModule.controller('UserInfoCtrl', ['$scope',
function($scope) {
$scope.userInfo = {
email: "1319639755@qq.com",
password: "253445528",
autoLogin: true
};
$scope.getFormData = function() {
console.log($scope.userInfo);
};
$scope.setFormData = function() {
$scope.userInfo = {
email: '2254513188@qq.com',
password: 'damoqiongqiu',
autoLogin: false
}
};
$scope.resetForm = function() {
$scope.userInfo = {
email: "1319639755@qq.com",
password: "253445528",
autoLogin: true
};
}
}
])
預(yù)覽
以上代碼創(chuàng)建模塊,這個(gè)模塊不以來任何東西,所以數(shù)組是空,
有了模塊需要建立一個(gè)控制器由控制器來控制數(shù)據(jù)模型和視圖,UserInfoCtrl,這個(gè)控制器放在了form上。
在$scope上賦一個(gè)對象userInfo,定義好登入需要的一些信息,
然后回到html綁定值,使用ng-model綁定值。
這樣這些輸入項(xiàng)就和數(shù)據(jù)模型綁定起來了,

在$scope上建立getFormData方法,打印userInfo的數(shù)據(jù)
如何調(diào)用$scope上的方法呢?在頁面按鈕標(biāo)簽使用ng-click="getFormData()"指令,就可以去執(zhí)行$scope上的方法。
點(diǎn)擊獲取數(shù)據(jù)按鈕,就會(huì)打印userInfo的數(shù)據(jù)

如果我修改了input上面的值會(huì)不會(huì)同步到數(shù)據(jù)模型中去,也就是$scope.userInfo對象上面去。

答案是數(shù)據(jù)修改了,也就是說視圖上的修改會(huì)自動(dòng)同步到數(shù)據(jù)模型上面去,
$scope.setFormData = function() {
$scope.userInfo = {
email: '2254513188@qq.com',
password: 'damoqiongqiu',
autoLogin: false
}
};
也可以通過程序修改數(shù)據(jù)模型,視圖同步改變。
$scope.resetForm = function() {
$scope.userInfo = {
email: "1319639755@qq.com",
password: "253445528",
autoLogin: true
};
}
重置表單
動(dòng)態(tài)切換標(biāo)簽樣式
雙向數(shù)據(jù)綁定還可以用在修改樣式上面,
.text-red {
background-color: #ff0000;
}
.text-green {
background-color: #00ff00;
}
<!doctype html>
<html ng-app="MyCSSModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="CSS1.css">
</head>
<body>
<div ng-controller="CSSCtrl">
<p class="text-{{color}}">測試CSS樣式</p>
<button class="btn btn-default" ng-click="setGreen()">綠色</button>
</div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script src="CSS1.js"></script>
</html>
var myCSSModule = angular.module('MyCSSModule', []);
myCSSModule.controller('CSSCtrl', ['$scope',
function($scope) {
$scope.color = "red";
$scope.setGreen = function() {
$scope.color = "green";
}
}
])


ng-class
這種方式有一個(gè)問題,真實(shí)項(xiàng)目中標(biāo)簽結(jié)構(gòu)很復(fù)雜,如果{{}}里面的值取錯(cuò)了,或者說沒有值,取成了null,就會(huì)發(fā)生一些比較詭異的情況。
為了避免這種狀況AngularJS提供了ng-class指令,
ng-class和原生的class是有去別的,它支持是可以接收一些表達(dá)式的 。
.error {
background-color: red;
}
.warning {
background-color: yellow;
}
<!doctype html>
<html ng-app="MyCSSModule">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="NgClass.css">
</head>
<body>
<div ng-controller='HeaderController'>
<div ng-class='{error: isError, warning: isWarning}'>{{messageText}}</div>
<button ng-click='showError()'>Simulate Error</button>
<button ng-click='showWarning()'>Simulate Warning</button>
</div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script src="NgClass.js"></script>
</html>
var myCSSModule = angular.module('MyCSSModule', []);
myCSSModule.controller('HeaderController', ['$scope',
function($scope) {
$scope.isError = false;
$scope.isWarning = false;
$scope.showError = function() {
$scope.messageText = 'This is an error!';
$scope.isError = true;
$scope.isWarning = false;
};
$scope.showWarning = function() {
$scope.messageText = 'Just a warning. Please carry on.';
$scope.isWarning = true;
$scope.isError = false;
};
}
])
<div ng-class='{error: isError, warning: isWarning}'>{{messageText}}</div>
這行代碼使用了ng-class,他是一個(gè)表達(dá)式,如果isError的值是true他就會(huì)用error這個(gè)樣式,如果isWarning的值是true他就會(huì)用warning這個(gè)樣式,
var myCSSModule = angular.module('MyCSSModule', []);
myCSSModule.controller('HeaderController', ['$scope',
function($scope) {
$scope.isError = false;
$scope.isWarning = false;
$scope.showError = function() {
$scope.messageText = 'This is an error!';
$scope.isError = true;
$scope.isWarning = false;
};
$scope.showWarning = function() {
$scope.messageText = 'Just a warning. Please carry on.';
$scope.isWarning = true;
$scope.isError = false;
};
}
])
這段js代碼中一開始是兩個(gè)值都是false,底下兩個(gè)按鈕分別執(zhí)行兩個(gè)不同的方法,


ng-show和ng-hide
控制一個(gè)標(biāo)簽的顯示和隱藏,
<!doctype html>
<html ng-app="MyCSSModule">
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-controller='DeathrayMenuController'>
<button ng-click='toggleMenu()'>Toggle Menu</button>
<ul ng-show='menuState.show'>
<li ng-click='stun()'>Stun</li>
<li ng-click='disintegrate()'>Disintegrate</li>
<li ng-click='erase()'>Erase from history</li>
</ul>
<div/>
</body>
<script src="js/angular-1.3.0.js"></script>
<script src="NgShow.js"></script>
</html>
var myCSSModule = angular.module('MyCSSModule', []);
myCSSModule.controller('DeathrayMenuController', ['$scope',
function($scope) {
$scope.menuState={show:false};
$scope.toggleMenu = function() {
$scope.menuState.show = !$scope.menuState.show;
};
}
])
這個(gè)例子是點(diǎn)擊按鈕切換列表項(xiàng)的顯示狀態(tài),
<ul ng-show='menuState.show'> menuState.show這個(gè)模型的值
按鈕點(diǎn)擊運(yùn)行toggleMenu方法
$scope.toggleMenu = function() {
$scope.menuState.show = !$scope.menuState.show;
};
每次運(yùn)行都會(huì)區(qū)一個(gè)和之前相反的值,也就是區(qū)非。


這是一種開關(guān)效果。
ng-hide是和ng-show是想反的動(dòng)作