angular基礎( 1.2 -- 2.0版本 )
教程推薦位置:http://www.angularjs.net.cn/tutorial/
本人是比較傾向《angular權威教程》和angular手冊結合的方式學習。
除錯工具極力推薦:ng-inspector
1、資料繫結
angular資料繫結的兩個方式:(1)ng-bind指令(2)差值表示式(3)ng-model雙向資料繫結
ng-bind和差值表示式都可以寫簡單的js表示式,ng-model只能繫結變數名。
ng-bind 和 ng-cloak 可以迴避閃爍問題(插值表示式在剛剛載入時顯示在頁面上)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>資料繫結</title> <script src="angular.js"></script> </head> <body> <!-- ng-app指定angular作用域 ng-init初始化資料值 --> <div ng-app="" ng-init="name='ion';pwd=123456;istrue=true"> <input type="text" ng-model="name"> <!-- 注意ng-bind會拿name覆蓋掉標籤內的所有內容 --> <div ng-bind="istrue?name:''">我叫:xxx</div> <div>我叫:{{name}}</div> </div> </body> </html> <!-- 可以通過控制檯-->
2、資料迴圈
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>資料迴圈</title> <script src="angular.js"></script> </head> <body> <div ng-app="" ng-init="items=[2,5,3,2];json={'a':1,'b':2,'c':3}"> <ul> <!-- track by 指定唯一key。 angular出於效能考慮需要資料和檢視有一一對應的關係,這裡陣列出現重複資料不指定唯一key會報錯 --> <!-- 使用track by 也會導致刪除陣列一個元素後$index全部發生了改變,檢視又要重新渲染 --> <li ng-repeat="(index,item) in items track by $index">{{index}}-{{item}}</li> </ul> <!-- 另一點值得注意的就是當item是陣列或者物件時即使內容相同也不需要指定唯一key,因為陣列或物件的即使內容相同,當時其都是new Array或者new Object出來的新物件,並不相等,如下程式碼測試: --> <button onclick="check0()">button0</button> <button onclick="check1()">button1</button> <button onclick="check2()">button2</button> <button onclick="check3()">button3</button> <ul> <!-- 這裡不能用$Index,因為這個是下標順序 --> <li ng-repeat="(key,value) in json">{{key}}-{{value}}</li> </ul> </div> <script> function check0(){ alert("1==1:"+(1==1)); //true } function check1(){ alert("'a'=='a':"+('a'=='a')); //true } function check2(){ alert("[1,2,3]==[1,2,3]:"+([1,2,3]==[1,2,3])); //false } function check3(){ alert('{"name":"ion","age":22}=={"name":"ion","age":22}:'+({"name":"ion","age":22}=={"name":"ion","age":22})); //false } </script> </body> </html>
3、ng環境與js環境
(1)ng環境與js環境不互通
<!DOCTYPE html> <html lang="en" ng-app=""> <head> <meta charset="UTF-8"> <title>ng環境與js環境不互通</title> <script src="angular.js"></script> </head> <body ng-init="a=2"> <input type="text" ng-model="a"> <input type="button" value="輸出" onclick="showmsg()"> <script> function showmsg() { console.log(a); //Uncaught ReferenceError: a is not defined } </script> </body> </html>
(2)ng事件(用法和js相似)
- ng-click
- ng-dbl-click
- ng-mousedown
- ng-mouseenter
- ng-mouseleave
- ng-mousemove
- ng-keydown
- ng-keyup
- ng-keypress
- ng-change
<!DOCTYPE html>
<html lang="en" ng-app="">
<head>
<meta charset="UTF-8">
<title>ng事件</title>
<script src="angular.js"></script>
</head>
<body ng-init="arr=[{name:'ion'}]">
<input type="text" ng-model="name">
//ng事件能操作ng環境的變數
<input type="button" value="輸出" ng-click="arr.unshift({name:name})">
<ul>
<li ng-repeat="json in arr">What you input is: {{json.name}}</li>
</ul>
</body>
</html>
(3) 模組與controller $scope作用域(打通ng環境與js環境)
<!DOCTYPE html>
<!-- 1.2用模組:將模組名寫在ng-app上 -->
<html lang="en" ng-app="test">
<head>
<meta charset="UTF-8">
<title>angular模組</title>
<script src="angular.js"></script>
<script>
//1.1宣告模組:module的第一個引數是模組名稱,第二個引數是該模組依賴於哪些模組,是個陣列
let mod = angular.module('test',[]);
//2.1寫controller,一個模組中可以有多個controller
mod.controller('ctrl1',function($scope){
// 這裡是ng環境配置方法,方法裡面的parseInt是js環境下的函式
$scope.parseInt = function (str){
return parseInt(str);
}
});
</script>
</head>
<!-- 2.2用controller -->
<body ng-controller="ctrl1">
<input type="text" ng-model="a">
<input type="text" ng-model="b">
<!-- 注意parseInt是js環境的函式,angular要呼叫要加到$scope域下 -->
{{parseInt(a)+parseInt(b)}}
</body>
</html>
4、內建過濾器和自定義過濾器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>系統過濾器</title>
</head>
<style>
div[ng-app] div{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
div[ng-app] div:nth-child(odd){background-color: #795548;}
}
</style>
<body>
<div ng-app="myApp" ng-controller="myController">
<div>
單價:<input type="number" ng-model="price" /> <br/>
數量:<input type="number" ng-model="quantity" /> <br/>
總價:{{(price*quantity) | currency}}
</div>
<div>
篩選資料顯示<br/>
<input type="text" ng-model="search" placeholder="輸入篩選條件" />
<ul>
<!-- 注意使用時需要加上冒號和篩選值 orderBy也是如此,相當於過濾器引數用冒號新增-->
<li ng-repeat="item in items | filter:search">
{{item}}
</li>
</ul>
</div>
<div>
自定義過濾器stringMerge<br/>
<!-- 傳參就往後面加“:[引數]”,但是注意第一個引數在管道符|前面 -->
字元拼接:<em>{{ msg | stringMerge:'are':'god' }}</em>
</div>
</div>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myController', ['$scope','$filter',function($scope,$filter) {
$scope.price = 9.99;
$scope.quantity = 2;
$scope.items=['大黑','小紅','大白','小蘭'];
//在JavaScript程式碼中可以通過$filter來呼叫過濾器
$scope.msg=$filter('lowercase')('ION');
}]);
app.filter('stringMerge', function() { //可以注入依賴
return function(text,text1,text2) {
return text+" "+text1+" "+text2;
}
});
</script>
</body>
</html>
自定義過濾器判斷字元是否被包含:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="angular.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myController">
<div ng-if="surname | isInclude:name">{{'ion' | isInclude:name}}</div>
</div>
</body>
<script>
//將控制器寫成【name】-Controller 而不是 【name】-Ctrl是一種最佳實踐
angular.module('myApp',[]).controller('myController',function ($scope) {
$scope.name = 'ion luo';
$scope.surname = 'luo';
}).filter('isInclude',function () {
return function (txt1,txt2) {
if(txt2.indexOf(txt1)>-1){
return true;
}
else{
return false;
}
}
});
</script>
</html>
5、內建服務和自定義服務
常見的angular內建服務有:$location、$http、$timeout()和$interval()
可以認為服務就是在angular應用的的一些函式(後兩個)或者物件(前兩個)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>內建服務</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
body p:nth-child(odd){background-color: #795548;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
$location服務用於返回當前頁面的URL地址:<br/>
{{myUrl}}
</p>
<p>
$http 是 AngularJS 應用中最常用的服務。服務向伺服器傳送請求,應用響應伺服器傳送過來的資料。<br/>
伺服器返回:{{myDate}}
</p>
<p>
$timeout 服務對應了 JS window.setTimeout 函式。<br/>
$interval 服務對應了 JS window.setInterval 函式。<br/>
在angular應用中最好使用angular的服務而不是js的相似功能函式,因為angular服務的支援性更好
用法一樣,我們舉一個$timeout服務例子,5s後顯示"歡迎您"。
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('myController',['$scope','$location','$http','$timeout',function($scope,$location,$http,$timeout){
// $location服務用於返回當前頁面的URL地址
$scope.myUrl = $location.absUrl();
// $http 是 AngularJS 應用中最常用的服務。服務向伺服器傳送請求,應用響應伺服器傳送過來的資料。
$http.get('welcome.php').then(function(response){
$scope.myDate = response.date;
},function(){
$scope.myDate = "返回資料失敗!";
});
// $timeout 服務對應了 JS window.setTimeout 函式。
//$interval 服務對應了 JS window.setInterval 函式。
$timeout(function(){
alert("歡迎您!");
},5000);
}]);
</script>
</html>
自定義物件服務
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定義服務</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
自定義服務:用於將十進位制數字轉化成十六進位制<br/>
<!-- 注意這裡更改input的值不會更新hex的值 -->
<input type="number" ng-model="decimalism"><br/>
{{ decimalism }}的十六進位制為:{{ hex }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//自定義物件服務
app.service('hexafy',function(){
this.myFun = function(param){
return param.toString(16);
}
});
app.controller('myController',function($scope,hexafy){
$scope.decimalism = 50;
$scope.hex = hexafy.myFun($scope.decimalism);
});
</script>
</html>
6、$http服務
get和post請求的簡寫格式:
$http.get('/someUrl', config).then(successCallback, errorCallback);
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
7、依賴注入
AngularJS 提供很好的依賴注入機制。以下5個核心元件用來作為依賴注入:
- (1)value
Value 是一個簡單的 javascript 物件,用於向控制器傳遞值(配置階段):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依賴注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//// 建立 value 物件 "defaultValue" 並傳遞資料
app.value('defaultValue',5);
//將 defaultValue 注入控制器
app.controller('myController',function($scope,defaultValue){
$scope.number = defaultValue;
});
</script>
</html>
- (2)service
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依賴注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//定義服務'calcService',該服務中有個方法square返回一個數字的平方
app.service('calcService',function(){
this.square = function(a){
return a*a;
}
});
//將服務注入控制器
app.controller('myController',function($scope,calcService){
$scope.number = calcService.square(5);
});
</script>
</html>
- (3)factory
factory 是一個函式用於返回值。在 service 和 controller 需要時建立。也就是說可以引入到service或者controller。通常我們使用 factory 函式來計算或返回值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依賴注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//建立一個 factory 'MathService'用於計算兩個數字的乘積
app.factory('MathService',function(){
var factory = {};
factory.multiply = function(a,b){
return a*b;
}
return factory;
});
//在service中注入factory,當然controller注入也可以
app.service('calcService',function(MathService){
this.multi = function(a,b){
return MathService.multiply(a,b);
}
});
//再將服務注入控制器
app.controller('myController',function($scope,calcService){
$scope.number = calcService.multi(5,6);
});
</script>
</html>
- (4)constant
constant(常量)用來在配置階段傳遞數值,注意這個常量在配置階段是不可用的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依賴注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//宣告一個常量
app.constant('constValue','5');
//將常量注入控制器
app.controller('myController',function($scope,constValue){
$scope.number = constValue;
});
</script>
</html>
- (5)provider
AngularJS 中通過 provider 建立一個 service、factory等(配置階段)。Provider 中提供了一個 factory 方法 get(),它用於返回 value/service/factory。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依賴注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
// 配置service/factory
app.config(function($provide) {
$provide.provider('MathService', function() {
this.$get = function() {
var factory = {};
factory.multiply = function(a, b) {
return a * b;
}
return factory;
};
});
});
//將MathService注入控制器
app.controller('myController',function($scope,MathService){
$scope.number = MathService.multiply(5,6);
});
</script>
</html>
8、路由
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>AngularJS 路由例項 - 菜鳥教程</title>
<script src="angular.js"></script>
<script src="https://cdn.bootcss.com/angular.js/1.7.0/angular-route.min.js"></script>
</head>
<body ng-app='routingDemoApp'>
<h2>AngularJS 路由應用</h2>
<ul>
<li><a href="#!/">首頁</a></li>
<li><a href="#!/computers">電腦</a></li>
<li><a href="#!/printers">印表機</a></li>
<li><a href="#!/blabla">其他</a></li>
</ul>
<div ng-view></div>
<script>
angular.module('routingDemoApp',['ngRoute'])
.config(function($routeProvider){
$routeProvider
.when('/',{template:'這是首頁頁面'})
.when('/computers',{template:'這是電腦分類頁面'})
.when('/printers',{template:'這是印表機頁面'})
.otherwise({redirectTo:'/'});
});
</script>
</body>
</html>
路由配置時設定物件:
AngularJS 路由也可以通過不同的模板來實現。
$routeProvider.when 函式的第一個引數是 URL 或者 URL 正則規則,第二個引數為路由配置物件。
路由配置物件語法規則如下:
$routeProvider.when(url, {
template: string,
templateUrl: string,
controller: string, function 或 array,
controllerAs: string,
redirectTo: string, function,
resolve: object<key, function>
});
引數說明:
-
template:
如果我們只需要在 ng-view 中插入簡單的 HTML 內容,則使用該引數:
.when('/computers',{template:'這是電腦分類頁面'})
-
templateUrl:
如果我們只需要在 ng-view 中插入 HTML 模板檔案,則使用該引數:
$routeProvider.when('/computers', { templateUrl: 'views/computers.html', });
以上程式碼會從服務端獲取 views/computers.html 檔案內容插入到 ng-view 中。
-
controller:
function、string或陣列型別,在當前模板上執行的controller函式,生成新的scope。
-
controllerAs:
string型別,為controller指定別名。
-
redirectTo:
重定向的地址。
-
resolve:
指定當前controller所依賴的其他模組。
9、元件通訊
(1)通過公共服務
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body ng-app="myApp">
<directive1></directive1>
<directive2></directive2>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//公共物件服務
app.service('shareService',function () {
this.names = [];
this.addName = function(name){
this.names.push(name);
}
});
//元素指令1,通過公共服務新增輸入值到公共服務names陣列
app.directive('directive1',function(shareService){
return {
restrict:"E",
template:"name: <input type='text' ng-model='new_name'/><br/><button ng-click='addName()'>Add</button>",
link:function (scope,element,attrs) {
scope.addName = function () {
if(scope.new_name){
shareService.addName(scope.new_name);
}
}
}
}
});
//元素指令2,通過公共服務讀取通過服務裡面的names值
app.directive('directive2',function (shareService) {
return {
restrict:"E",
template:"<ul><li ng-repeat='list in lists'>{{list}}</li></ul>",
link:function (scope,element,attrs) {
scope.lists = shareService.names;
}
}
});
</script>
</html>
(2)通過link的attrs實現同一個dom下元件通訊
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body ng-app="myApp">
<directive1 directive2></directive1>
</body>
<script src="angular.js"></script>
<script>
<!--
每個directive在定義的時候都有一個link函式,函式簽名的第三個引數是attrs,代表在該directive上面的
所有atrributes陣列,attrs提供了一些方法,比較有用的是$set和$observe,前者可以自定義attr或修改已經有
的attr的值,後者可以監聽到該值的變化。利用這種方式,我們可以讓在位於同一個dom元素上的兩個directive進
行通訊,因為它們之間共享一個attrs陣列。
-->
var app = angular.module('myApp',[]);
app.directive('directive1',function(){
return {
restrict:"E",
template:"<span>{{ time | date:'yyyy-MM-dd HH:mm:ss'}}</span>",
link:function (scope,element,attrs) {
attrs.$observe('showValue',function (newValue) {
scope.time = newValue;
});
}
}
});
app.directive('directive2',function ($interval) {
return {
restrict:"A",
link:function (scope,element,attrs) {
let defInterval = $interval(function () {
attrs.$set("showValue",new Date().getTime());
},1000);
scope.$on('$destory',function(){
$interval.cancel(defInterval);
});
}
}
});
</script>
</html>
10、系統指令
全部angular系統指令可見angular參考手冊,http://www.runoob.com/angularjs/angularjs-reference.html。下面介紹些常用系統指令:
(1)ng-class 和 ng-style
<!DOCTYPE html>
<html ng-app="">
<head>
<meta charset="utf-8">
<title>常見系統指令</title>
<script src="angular.js"></script>
<style>
.container{width:100px;height:100px;background-color:yellow}
.box{display: inline-block; }
</style>
</head>
<!-- 注意ng-style裡面的屬性兩個單詞需要連寫並且後首字母大寫 -->
<body ng-init="a='width:100px;height:100px;background-color:red';
b={width:'100px',height:'100px',backgroundColor:'blue'};
c='container box';
d=['container','box']">
<div style="{{ a }}"></div>
<div ng-style="b"></div>
<div class="{{ c }}"></div>
<div ng-class="d"></div>
</body>
</html>
效果:
(2)ng-switch
該指令和 ng-if 一樣當滿足條件才渲染到HTML中。(注意 ng-if 沒有 ng-else 指令來做if-else條件結構,需要時使用ng-switch)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>常見系統指令</title>
<script src="angular.js"></script>
</head>
<body ng-app="">
<select ng-model="site">
<option value="taobao">淘寶</option>
<option value="zhihu">知乎</option>
<option value="jingdong">京東</option>
</select>
<div ng-switch="site">
<div ng-switch-when="taobao"><h1>淘寶</h1></div>
<div ng-switch-when="zhihu"><h1>知乎</h1></div>
<div ng-switch-when="jingdong"><h1>京東</h1></div>
<div ng-switch-default><h1>請選擇 >>>>>></h1> </div>
</div>
</body>
</html>
(3) ng-bind-html 和 $sce.trustAsHtml()
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>ng-bind-html和$sce</title>
<script src="angular.js"></script>
</head>
<body ng-controller= "myController">
<div ng-bind-html="a"></div>
</body>
<script>
var app = angular.module('myApp',[]);
app.controller('myController',function($scope,$sce){
$scope.a = $sce.trustAsHtml("歡迎來到<a href='https://blog.csdn.net/ion_L' target='_blank'>ion的部落格</a>");
});
</script>
</html>
注意,低版本的angluar可以直接繫結HTML程式碼,但是在anglar1.6.4之後必須加上$sce才可以,否則會出現如下報錯。
關於$sce的具體內容見:https://www.cnblogs.com/xing901022/p/5100551.html
11、Angular概念圖