Angular的学习
Angular的學習
- Angular的特性.
- MVC : 在前端引入了MVC的設計模式
- 模塊化開發
- 自動的雙向數據綁定
*語義化標簽(自定義標簽) - 依賴注入
- 其核心就是通過指令擴展了HTML,通過表達式綁定數據到HTML
- Angular不推崇DOM操作
- ng最主要是用來實現spa應用 - SPA (單頁面應用程序)
我們了解了Angular的特性,再來著手學習可能會對這些特性有更深刻的體會
MVC設計模式
1.現實生活中的MVC
現實生活中的分工合作案例 – 大飯店
- 采購:負責原材料采購.
- 小工: 打雜,洗菜,洗碗.
- 廚師: 切菜 炒菜
- 服務員:端菜 迎賓
- 收銀員: 收錢.
- 采購:指揮協調其它人員工作.
在一些街邊小飯館其實這些事情完全是交給一個人去做 –> 老板
- 所有的事情都是這1個人去做.
對比一下這兩種經營方式的區別
- 大飯店: 正規,分工合作,各司其職,效率高.
- 小飯館: 不正規,慌亂.效率低下.
同樣的事情兩種實現方式
- 都是將客人點的菜展示到餐桌上.
- 不同的單位使用了不同的流程.
- 大飯店: 每個人負責1個流程.高效并且可維護程度極高. 掛了1個 人,不影響其它人.只換這1個人就可以.
- 小飯館: 1個人負責整個流程,效率低下并且可維護程度極低,老板掛了,飯館就得關門.
由此可見,分工是多么的重要
代碼中的MVC
實際上,我們寫網站的過程,和開飯店的原理和流程極其相似,我們寫網站是將數據展示到頁面上.
目前,我們寫代碼都是一股腦的將所有的代碼寫在一起,這樣去寫固然沒有什么問題,因為你終究還是將效果實現了.
但是這樣做的后果是可怕的,隨著項目越來越大,你的代碼將變得非常難以維護.
為了讓我們的代碼更加容易的維護,也為了使得我們的代碼層次更加分明
我們將我們的代碼分為三部分
- M - Model 數據 數據實體,用來保存頁面要展示的數據.
- V - View 視圖 負責顯示數據的,一般其實就是指的html頁面.
- C - Controller 控制器 控制整個業務邏輯,負責處理數據,比如數據的獲取,以及數據的過濾,進而影響數據在視圖上的展示.
這樣,這3部分各司其職,分工合作,我們的代碼就會變得更有層次并容易維護.
這樣的程序設計模式,我們就叫做MVC設計模式.
MVC是由后端而來,由于受到前端技術的限制便有了一些細節的調整,
- 進而出現了很多MVC的衍生版(子集)如MVVM、MVW、MVP、MV*等。
模塊化
使用AngularJS構建應用(App)時是以模塊化(Module)的方式組織的,即將整個應用劃分成若干模塊,每個模塊都有各自的職責,最終組合成一個整體。
采用模塊化的組織方式,可以最大程度的實現代碼的復用,可以像搭積木一樣進行開發。
1. 定義應用
通過為任一HTML標簽添加ng-app屬性,可以指定一個應用,表示此標簽所包裹的內容都屬于應用(App)的一部分。通俗的理解就是: ng-app屬性標簽被Angular管理,包括其中的子標簽.Angular會認為這是一個應用,將其作為一個應用來看待。2. 定義模塊
AngularJS提供了一個全局對象angular,調用該全局對象的module()方法可以創建一個模塊.該方法返回一個模塊對象.這個模塊對象就是AngularJS用來管理應用的對象. <!DOCTYPE html><!--為html標簽定義ng-app屬性 代表整個文檔都被ng管理--><html lang="en" ng-app="myApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.js"></script></head><body><script>//調用全局對象angular的module方法創建一個模塊.//第一個參數: 模塊要管理的標簽范圍,寫上ng-app屬性的值.//第二個參數: 模塊依賴,數組,如果不需要依賴,就直接寫一個空數組就可以.//返回值:返回的app對象,我們可以認為這個對象就是ng用來管理這個模塊的.var app = angular.module('myApp',[])</script></body></html> ### 3. 定義控制器 接下來我們可以通過app模塊對象來創建控制器. 調用app模塊對象的controller方法,就可以創建控制器. var app = angular.module('myApp',[])//調用app的controller方法創建控制器.//第一個參數: 要將創建的控制器關聯到指定的View上,字符串.//第二個參數: 這是一個數組,數組的其中一個元素是'$scope',// 數組的最后一個元素必須是1個function 參數是$scope// 先把$scope寫死,后面學了服務就知道$scopeapp.controller('demoCtrl',['$scope',function ($scope) {}]);- 但是這個時候,我們只是創建了控制器,并沒有將控制器和視圖關聯起來.
- 視圖是用來負責顯示數據的,控制器是來處理數據模型,并將數據模型給視圖展示.
- 視圖就是我們的html頁面. 所以我們可以指定1個html元素(視圖)與這個控制器相關聯.
為這個html元素指定1個ng-controller屬性.值為創建controller的第1個參數的值.
數據模型
控制器負責處理制造模型數據.
視圖負責顯示控制器制造的模型數據.
那么控制器如何制造數據呢?
Angular的基本結構
Angular的基本結構和工作流程
- 指定Angular管理的范圍 ng-app
- 創建模塊 angular.module()
創建角色
- 3.1 創建控制器 app.controller()
- 3.2 指定與控制器關聯的視圖 ng-controller
控制器制造數據模型并附到 scope scope.xx = yy;
- 在視圖中顯示模型數據 {{}}
下面舉個例子來對Angular的結構有更清晰的認知
<!DOCTYPE html> <!-- 1.指定整個html文檔都被ng管理--> <html lang="en" ng-app="ngApp"> <head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.js"></script></head> <body><!-- 將視圖與控制器相關聯 --><table ng-controller="stuList"><tr><td>編號</td><td>姓名</td><td>性別</td><td>年齡</td></tr><tr ng-repeat="stu in students"><!-- 遍歷數組,并循環生成html --><td>{{stu.id}}</td><td>{{stu.name}}</td><td>{{stu.gender}}</td><td>{{stu.age}}</td></tr></table> <script>//2.創建模塊var app = angular.module('ngApp',[]);//3.創建MVC角色. 控制器,視圖app.controller('stuList',['$scope',function ($scope) {//制造數據模型,并綁定到$scope中.$scope.students = [{id:1,name:'小明',gender:'男',age:18},{id:2,name:'小花',gender:'女',age:16},{id:3,name:'小強',gender:'男',age:14},{id:4,name:'小東',gender:'男',age:19},{id:5,name:'小常',gender:'女',age:20}];}]); </script> </body> </html>Angular指令
- HTML在構建應用(App)時存在諸多不足之處
- AngularJS通過擴展一系列的HTML屬性或標簽來彌補這些缺陷
- 所謂指令就是AngularJS自定義的HTML屬性或標簽
- 這些指令都是以ng-做為前綴的,例如ng-app、ng-controller、ng-repeat等
1. 內置指令
- ng-app 指定應用根元素 也就是ng管理的范圍.可以使用全局對象angular的module方法根據該屬性的值創建模塊對象.
- ng-controller 指定與控制器關聯的視圖.
- ng-show 控制元素及其子元素是否顯示 true->顯示 false->不顯示
- ng-hide 控制元素及其子元素是否隱藏 true->隱藏 false->不隱藏
- ng-if 控制元素及其子元素是否創建 true->創建 false->刪除.
- ng-src 增強圖片路徑. src=”“雖然能顯示,但是會報錯.報錯的原因.
- ng-href 增強href路徑
- ng-class 值為對象 {red:true} 表示會添加1個red類名到元素身上. {red:false}不會將red類名添加到元素身上.
- ng-include 將外部文件包含進來.一般用在頁面的公共部分.被請求的頁面是以ajax的方式請求的. ng-inlcude=“‘path’”需要注意的是,給該屬性賦值的時候,屬性本身的值應該使用雙引號引起來,但是其中的路徑還要使用單引號引起來.
- ng-disable 是否禁用表單元素
- ng-readonly 是否只讀
- ng-checked 原生的checked屬性帶有歧義,ng補充1個新的指令ng-checked 其值bool類型 true選中 false不選中.
- ng-selected 是否選中
后續還會介紹其他內置指令
2. 自定義指令
- AngularJS不僅提供了功能強大的內置指令.還提供了一套允許我們自定義指令的機制.
- 如果我們覺得ng提供的指令不夠強大和好用,我們完全可以定義我們自己的指令.
模塊對象app,提供了一個directive方法,這個方法就可以讓我們自定義指令.
該方法需要兩個參數
第1個參數 指令的名稱 - 指令名稱不能包含符號,如果指令名稱是tag,那么直接使用tag就行. 如果指令是hmTag,那么要使用hm-tag
第2個參數 回調函數
在ng解析這個指令的時候,就會自動去執行這個回調函數. 這個回調函數必須要按照要求返回1個對象. restrict: ECMA E:Element C:Class M:Mark A:Attribute 自定義指令 replace: bool值,是否替換原有標簽. template: 模板,自定義指令將被替換成什么. templateUrl:加載外部文件 給一個需要加載的文件的路徑.
數據單向綁定
- 所謂的數據的單向綁定,
- 指的就是在控制器中制造數據模型,
- 并將數據模型顯示在視圖上的過程.
- 數據單向綁定的步驟
- 先在控制器中制造數據
- 在視圖中使用綁定符號{{}}將控制器制造的數據模型顯示
雖然ng-bind與{{}}使用效果是一樣的,
但是在更多的地方我們仍然使用{{}}的場景更多一些
比如 : 這樣的情況使用{{}}就方便的很多了.
“`js
大家好,我叫{{name}},我今年歲{{age}}了
“`
### 解決閃爍的問題
- 雖然{{}}符號和ng-bind指令作用是一樣的.但是他們在效果上有一些些區別
- 使用{{}}符號有可能會出現閃爍現行(當吧ng文件的引入放在頁面后面的時候)
- 出現閃爍的原因
- 瀏覽器先渲染html頁面.遇到ng指令不認識 原因輸出.
- 而后,ng開始工作,渲染綁定數據.
- 所以,中間有這么一個閃爍的過程.
解決閃爍問題 - 第一種方式: 將ng文件的引入放在head標簽中.
- 第二種方式: 為標簽添加1個ng-cloak指令.就可以解決.
ng-cloak的原理. - ng會自動的生成1段css代碼,將這個標簽隱藏.
- 當數據綁定工作完成之后,再顯示這個標簽.
數據雙向綁定
- ng-model指令可以作用于表單元素.
該指令的作用
- 聲明1個變量.該屬性的值就是聲明的變量.
- 這個變量的值和表單元素的值是相互影響的.
- 表單元素的值發生變化,這個變量的值也會跟著發生變化.
- 這個變量的值發生變化,表單元素的值也會跟著發生變化.
- 這樣的數據綁定,就叫做雙向數據綁定.
ng-init指令
數據模型的初始化,我們一般是放在控制器中.
為 scope對象附加屬性的方式來追加.然后在視圖中就可以直接綁定數據.實際上,Angular還提供了一種更為簡便的方式來初始化模型數據.就是使用ng?init屬性.使用ng?init初始化的變量在控制器中通過 scope仍然可以訪問
“`js
{{name}} {{age}}
var app = angular.module('hmApp',[]);
“`
對于一些復雜的數據模型,比如數組、對象明顯在controller中初始化就方便的很多.
Angular事件處理
1 ng-click
原生js中如果需要綁定點擊事件,在html元素中使用onclick屬性,
指定該屬性的值為一個函數調用.
那么這個函數就是全局的函數,會造成全局污染.
“`js
function login(){
.......
}
登錄
“`
Angular為了解決這個問題,使用了1個ng指令ng-click
這是Angular中的點擊指令,為其賦值一個函數,不同的是,這個函數需要在控制器中綁定到$scope對象中.
那么這個函數就不再是一個全局的函數,就不存在全局污染的問題了.
2 ng-moueover
其實原理是一樣的,這是ng的指令 用來綁定鼠標移入事件.
<div ng-controller="demoCtrl"><button ng-click="login()">按鈕</button><input type="text" ng-mouseover="mover()"></div><script>var app = angular.module('hmApp',[]);app.controller('demoCtrl',['$scope',function ($scope) {$scope.login = function () {alert("正在登錄,請稍后.....");};$scope.mover = function () {console.log("鼠標移入了.....");}}]);</script>其他事件指令
其實到這里我們可以總結出一些規律了
Angular的事件指令是在原生指令屬性的基礎之上把on去掉替換為ng-
onclick –> ng-click
onmouseover –> ng-mouseover
onkeyup –> ng-keyup
……
數據處理
1 ng-repeat
用于循環生成標簽,并綁定數據.
可以遍歷數組.
可以遍歷對象
<!DOCTYPE html><html lang="en" ng-app="hmApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script></head><body><div ng-controller="processDataView"><ul><li ng-repeat="item in lessons"></li></ul><table><tr><!--遍歷對象,item迭代變量直接就是每一個屬性的值--><td ng-repeat="item in student">{{item}}</td><!--如果希望得到屬性名稱和屬性值 可以像下面這樣如果是數組,key拿到的就是下標 --><td ng-repeat="(key,item) in student">{{key}}:{{item}}</td></tr></table></div><script>var app = angular.module('hmApp',[]);app.controller('processDataView',['$scope',function ($scope) {$scope.lessons = ['html','css','js','jQuery'];$scope.student = {name:"杰克",age:18,gender:"男"};}])</script></body></html>ng-switch
該指令的作用與js的switch-case非常相像
判斷變量的值,如果變量的之與列出的任意1個值相等,則執行其中的邏輯.
語法規則
也可以下面這樣使用
<!DOCTYPE html><html lang="en" ng-app="hmApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script></head><body><div ng-controller="demoCtrl" ng-switch="name"><div ng-switch-when="rose">Rose</div><div ng-switch-when="jack">Jack</div><div ng-switch-when="lily">Lily</div><div ng-switch-when="poly">Poly</div><div ng-switch-default>默認選項</div></div><script>var app = angular.module('hmApp',[]);app.controller('demoCtrl',['$scope',function ($scope) {$scope.name = "jack";}]);</script></body></html>Angular作用域
1.相互獨立的視圖/控制器,他們的作用域($scope)也是相互獨立,互不影響的.
<!DOCTYPE html><html lang="en" ng-app="hmApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script></head><body><div ng-controller="demoCtrl1"></div><!--在與第2個控制器關聯的視圖上,無法訪問與第1個視圖相關聯的控制器的數據--><div ng-controller="demoCtrl2"></div><div ng-controller="demoCtrl3"></div><script>var app = angular.module('hmApp',[]);app.controller('demoCtrl1',['$scope',function ($scope) {$scope.name = "杰克";//為第1個控制器/視圖的$scope綁定了一個數據.//這個數據只能在與當前控制器相互關聯的視圖上訪問.//不能在與別的控制器關聯的視圖上訪問.}]);app.controller('demoCtrl2',['$scope',function ($scope) {}]);app.controller('demoCtrl3',['$scope',function ($scope) {}]);</script></body></html>2.父子關系的視圖所對應的控制器,在子視圖/控制器中
可以訪問父視圖/控制器中$scope的數據.
* 子視圖中可以訪問父視圖中的數據.
* 父視圖不能訪問子視圖中的數據.
* 如果訪問的變量在視圖中有定義,那么優先訪問子視圖自己的,
如果該變量子視圖自己沒有定義,
這個時候再去嘗試查找父視圖中是否有定義這個數據.
3.根作用域
- 我們可以使用ng-init指令來初始化一個變量,在父級元素上.
- 那么這個父級元素下所有的子視圖都可以訪問.
過濾器
在AngularJS中使用過濾器格式化展示數據, 在“{{}}”中使用“|”來調用過濾器,使用“:”傳遞參數。1.內置過濾器
日期過濾器 {{now|date:’yyyy-MM-dd hh:mm:ss’}}
貨幣符號過濾器 {{price|currency}}
- 默認是美元符號
- 如果想要顯示其它貨幣符號
保留指定位數的小樹
{{price|currency:'¥':2}}這樣顯示的就是人民幣符號 并四舍五入保留兩位小數轉換為大寫
{{info|uppercase}}將info的值轉換為大寫顯示轉換為大寫
{{info|lowercase}}將info的值轉換為大寫顯示截取數組/字符串中指定位數的元素.
{{arr|limitTo:n}}正數從左往右截取n個元素負數從右往左截取n個元素arr可以是1個數組也可以是一個字符串.字符串的話就截取每一個字符.處理數字的過濾器number可以控制小數的位數
{{num|number:2}} 保留2位小數輸出.json過濾器 將對象轉換為json字符串
{{obj|json}} 將obj對象轉換為json字符串輸出.實際上,不使用json過濾器它也會這么做.orderBy過濾器
{{students|orderBy:'score'}} 將student數組中的對象以score屬性為參照進行排序 默認是升序.{{students|orderBy:'score':true}} 降序filter 過濾器
{{students|filter:{score:90} }} 過濾出數組中對象分數等于90的對象.特別注意: 參數對象必須和后面的大括弧有一個空格.自定義過濾器
模塊對象提供了一個filter方法,允許我們自定義過濾器.
該方法的參數說明
- 第一個參數: 過濾器名稱
第二個參數: 回調函數 - 當執行我們自定義的過濾器的時候,就會自動來執行這個回調函數.
<div ng-controller="demoCtrl">{{name|highven}} </div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope', function ($scope) {$scope.name = "jack";}])app.filter('highven',function () {console.log("我被執行了");}); </script>
通過調試發現,回調函數確實被執行了,但是報錯了.報錯的原因是我們沒有按照要求來寫這個回調函數的參數和返回值.
要求這個回調函數必須返回一個函數.
返回的這個函數就是過濾器,來處理過濾數據的.
這個返回的函數
* 第1個參數: 需要處理過濾的數據.
* 后面的參數: 處理數據的時候,自己還需要的另外的參數
* 返回值: 處理完畢后返回的數據,被顯示出來.
自定義過濾器案例:將一個英文句子中首個單詞的首字母大寫.
app.filter('firstBig',function () {return function (data) {return data[0].toUpperCase()+data.slice(1);//slice從指定位置提取字符串 沒有第2個參數就一直提到最后.}});依賴注入
Angular內部封裝了很多的模塊,我們作為開發者在進行開發的時候,直接拿來使用就行, 也就是說,如果我們要使用別人封裝好的模塊,就必須要先引入別人的模塊. 沒有這個模塊,可能就實現不了這個功能. 也就是我們依賴于這個模塊. 比如jQuery是我們依賴的.理解依賴注入
* 依賴關系: 就是模塊之間的依賴關系.比如bootstrap依賴于jQuery,它們之間的關系就是依賴關系.
依賴解決: 建立這種依賴關系的方案.比如之前我們使用1個script.src來解決依賴關系.
注入: 是解決依賴的另外一種方式. 你可以形象的理解,A依賴于B,那么就像打針一樣,把B注入 到A中,那么A中就可以使用B了.它們的依賴關系就建立成功了.
- 所以,依賴注入是建立依賴關系的一種方式.
1.行內式注入
在視圖中之所以能夠訪問到控制器綁定到 scope中的值,完全是因為 scope的存在.
實際上, scope是Angular的一個模塊.這個模塊在視圖中可以直接訪問使用.但是在控制器的回調函數中,無法直接訪問使用這個 scope模塊.
所以,這個回調函數必須要依賴$scope模塊.
創建控制器的時候.第2個參數是一個數組.
數組的最后一個元素是控制器的回調函數.
前面的元素其實就是表明回調函數要依賴Angular的那些模塊.
- 第1個元素. ‘ scope′表明控制器要依賴 scope這個模塊.
- 回調函數的參數: Angular會將$scope模塊通過函數的形參注入到函數的內部,
讓函數去使用. 實際上,回調函數的形參是可以任意的,
這里之所以取得和模塊的名字一樣,是為了讓我們的代碼看起來更加具備可讀性.Angular提供的模塊還有很多,我們也可以將其注入到控制器中.
這樣的注入方式,我們就叫做行內式注入
<body><div ng-controller="demoCtrl"><!-- 之所以能在這里訪問控制器中綁定到$scope的name數據.完全是因為$scope的存在.實際上,$scope是ng的一個模塊,這個模塊是直接可以在視圖中訪問的.但是在控制器的回調函數中,無法直接訪問使用這個$scope模塊那么就需要將這個$scope模塊注入到控制器的回調函數中--><span></span></div><script>var app = angular.module('hmApp', []);/** 第二個參數是一個數組.* 數組的第一個元素, '$scope'表示控制器要依賴 $scope 這個模塊.* Angular會通過回調函數的參數將$scope模塊注入到回調函數內部.* 供控制器回調函數內部使用.* 這個時候,回調函數內部就可以通過形參拿到$scope這個模塊.* 將其與視圖共享之,傳遞數據之.*/app.controller('demoCtrl', ['$scope', function ($scope) {$scope.name = "杰克";}])</script></body>推斷式注入
推斷式注入的寫法很簡單,第2個參數直接寫1個回調函數就可以.
app.controller('demoCtrl', function ($scope) {$scope.name = "杰克"; });Angular在注入的時候,會根據回調函數的參數名稱進行推斷.
如果參數名稱是 scope,那么就會將 scope這個模塊進行注入
如果參數名稱是 http,那么就會將 http這個模塊進行注入
所以,使用這種注入方式,回調函數的形參必須要和Angular的模塊名稱一致.否則將無法注入.
推斷式注入的缺點: 當進行代碼壓縮的時候,就會出問題,因為代碼壓縮會將形參替換.那么這個時候Angular就無法正常注入了.
所以,我們推薦使行內式注入
Angular服務
服務,可以理解為就是一個對象或者函數,對外提供特定的功能.
其實你完全可以認為它就是一個模塊,不同的模塊提供不同的功能.
當我們要使用某1個模塊的時候,將其注入到控制器中便可以使用
log服務
作用:在控制臺輸出調試信息. $log是1個對象.
調試信息分為如下幾個級別.
* error 錯誤信息
* debug debug信息
* info 打印信息
* log 正常打印日志
* warn 警告信息
分別調用$log對象的這幾個方法就可以輸出對應格式的信息.
注意: 要正確調整瀏覽器控制臺log過濾
$timeout服務
作用:在指定的時間做事情,$timeout是一個函數.
js
<body>
<div ng-controller="demoCtrl">
<!--所以,這里的name也要等到3秒鐘后才會顯示出來.-->
<p>我的名字叫做{{name}}</p>
</div>
<script>
var app = angular.module('hmApp', []);
app.controller('demoCtrl', ['$scope','$timeout', function ($scope,$timeout) {
$scope.now = new Date();
//表示3秒鐘后為name賦值
$timeout(function () {
$scope.name = "小明";
},3000);
}]);
</script>
</body>
$interval服務
作用:每隔指定的時間就做指定的事情.
<body><div ng-controller="demoCtrl"><!--所以,這里的數據每一秒鐘就變化一次--><p>現在時間是:{{now|date:'yyyy-MM-dd HH:mm:ss'}}</p></div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope','$interval', function ($scope,$interval) {$interval(function () {$scope.now = new Date();},1000);//每隔一秒鐘就為now重新賦值.}]);</script></body>interval函數,返回1個數據.調用 interval.cancel(返回值)可以停止計時器
<body><div ng-controller="demoCtrl"><p>現在時間是:{{now|date:'yyyy-MM-dd HH:mm:ss'}}</p><button ng-click="stop()">停止</button></div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope','$interval', function ($scope,$interval) {var stop = $interval(function () {$scope.now = new Date();},1000);$scope.stop = function () {$interval.cancel(stop);}}]);</script></body>$filter服務
作用:格式化數據 filter這是1個函數狹義的解釋:在控制器中格式化數據.過濾器在視圖中格式化數據,而 filter在控制器中格式化數據.
用法實際上,和過濾器用法非常相像.并且$filter服務支持自定義過濾器
案例演示 :
<body><div ng-controller="demoCtrl"><ul><li><span>現在時間是:{{now}}</span></li><li><span>{{intro}}</span></li></ul></div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope','$filter',function ($scope,$filter) {//傳入date 返回的函數就是和處理日期相關的函數var date = $filter('date');//第1個參數: 待處理的日期數據//第2個參數: 過濾器參數//返回值:被處理過的數據$scope.now = date(new Date,'yyyy-MM-dd HH:mm:ss');var uCase = $filter('uppercase');$scope.intro = uCase('this is itcast!');}]);</script></body>$http服務
1.$http服務基本使用
作用:用于向服務器發送異步請求 這是1個函數.
參數:傳入1個符合條件的對象.
* url:請求地址
* method:請求方式get/post
* data:{} 當請求方式為post的時候 使用data傳遞數據.
* params:{} 當請求方式為get的時候,使用params傳遞數據.
* headers:{} 設置請求頭信息
* .then()函數傳入兩個回調函數.
* 第1個回調,當請求成功后執行,參數info。通過info.data拿到返回的數據
* 第2個回調,當請求失敗后執行.
案例演示
<body><div ng-controller="demoCtrl"><table><tr><th>姓名</th><th>年齡</th></tr><tr ng-repeat="stu in data"><td>{{stu.name}}</td><td>{{stu.age}}</td></tr></table></div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope','$http',function ($scope,$http) {$http({url:'example.php',method:'get'}).then(function (info) {$scope.data = info.data;},function () {});}]);</script></body>2. $http服務傳遞數據的 格式
當請求類型是get時,向服務器傳遞的數據必須要放在params中,以對象的形式.
get請求發送的數據格式是 queryString類型的
當請求類型是post時,向服務器發送的數據必須要放在data中.
設置發送數據的類型.
data要以鍵值對的字符串形式.
客戶端以post方式向服務器發送數據時.必須要指定發送數據的類型.
因為不同的數據格式在服務器處理的方式是不一樣的.
常見的數據格式
application/json –> 這種格式叫做formdata
application/x-www-form-urlencoded –> 這種格式叫做payload
jQuery的Ajax默認的數據類型就是application/x-www-form-urlencoded
AngularJS的$http默認支持的是application/json
$http跨域
基于瀏覽器的同源策略,Ajax異步是無法實現跨域請求的.
實現跨域請求的解決方案
* src屬性是天然支持跨域的.
* 所以,我們可以利用script標簽的src屬性來跨域請求數據.
* 如果使用script標簽的src屬性來跨域請求,會將請求回來的數據作為js代碼執行.
3.1 AngularJS的跨域
AngularJS已經幫我們封裝好了一切.
$http({url:'',//請求地址method:'jsonp', //jsonp就可以(只支持不帶有 . 的callback接口)params:{//傳遞額外數據.}}).then(function(info){}).catch(function(){});自定義服務
1. 使用factory自定義服務
模塊對象有一個方法叫做factory允許我們自定義服務.
該方法需要兩個參數
- 第1個參數,服務名稱.
- 第2個參數,是1個數組,前面的元素寫依賴,最后一個元素是回調函數.
這么寫會報錯,原因是回調函數我們沒有按照AngularJS的要求來寫返回值.
語法上,自定義服務的回調函數允許返回任意的值,但是既然是1個服務,1個模塊,就應該返回1個功能,所以一般情況下,自定義服務的回調函數我們返回1個函數或者1個對象
2. 使用service自定義服務
模塊對象有1個方法叫做service,也能自定義服務.
該方法有兩個參數
* 第1個參數,自定義服務的名稱
* 第2個參數,數組,依賴,最后1個是回調函數.
與factory不同的是,service不需要手動返回數據.
直接用this,為返回的對象添加屬性或者方法.
所以,service與factory的區別就像構造函數與工廠方法的區別
配置塊
在AngularJS執行流程中的配置和運行這一流程,允許開發者對AngularJS的模塊進行自定義的配置.
這樣就可以讓后續ng的執行按照我們的意愿來.
模塊對象提供了一個config方法,允許我們ng模塊進行配置.
* 需要1個參數 這個參數是1個數組
* 數組中,寫上開發者需要配置的模塊Provider.最后是1個回調函數.給回調函數注入模塊.
* 在回調函數中,對模塊進行配置.
每一個服務,都對應一個Provider,比如 log模塊對應 logProvider, http對應 httpProvider ……
在通過config方法配置模塊的時候,其實是通過模塊對應的Provider來進行配置的.
1.配置$filter
每一個Provider都有自己的方法,我們不可能記住,也記不住.
所以,建議大家勤查AngularJS官方API
2.配置$http跨域白名單
app.config(['$sceDelegateProvider', function ($sceDelegateProvider) {// 設置白名單$sceDelegateProvider.resourceUrlWhitelist(['http://api.map.baidu.com/telematics/v3/weather']);}])$http({url:'http://api.map.baidu.com/telematics/v3/weather',method:'jsonp',params:{ak:'0A5bc3c4fb543c8f9bc54b77bc155724',location:'深圳市',output:'json'}}).then(function (info) {console.log(info)});運行塊
AngularJS中的模塊(服務)我們都是以注入的方式來使用的.
實際上,AngularJS中的模塊是可以獨立運行的.
模塊對象提供了一個run方法,可以直接運行某些服務.不需要依賴控制器.
* 需要1個參數,這是1個數組.
* 在數組中寫上要運行的模塊,最后一個是1個回調函數.順序注入.
* 在這個回調中的代碼就會在配置運行階段執行.
常見的模塊.
* http可以在一啟動的時候,就發起ajax異步請求? rootscope 為這個服務追加數據,就相當于追加到了根作用域中. 相當于ng-init
* $log
* ……
案例:
<body><div ng-controller="demoCtrl"></div><script>var app = angular.module('hmApp', []);app.run(['$log','$http','$rootScope',function ($log,$http,$rootScope) {//在這里可以脫離控制器使用模塊對象.//$rootScope 模塊代表根作用域,往其中追的數據就相當于是追在了根作用域中.$rootScope.name = "杰克";//在所有的作用域中都可以訪問.}])app.controller('demoCtrl', ['$scope', function ($scope) {}]);</script></body>AngularJS的路由
1. AngularJS路由的簡單使用
實現單頁面的原理
* 通過hashchange事件監聽到錨點的變化,進而可以實現為不同的錨點顯示不同的視圖,單頁面應用就是基于這一原理實現的。
AngularJS對這一實現原理進行了封裝,將錨點的變化封裝成路由(Route)。
將angular-route.js引入到當前項目中.
<head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script><script src="lib/angular-route.js"></script></head>然后創建模塊應用,需要注意的是,我們現在創建的模塊應用要依賴于ngRoute模塊.
<script>var app = angular.module('hmApp', ['ngRoute']);//新創建的模塊要依賴于 ngRoute 模塊app.controller('demoCtrl', ['$scope', function ($scope) {}])</script>只要app模塊運行了,那么ngRoute模塊就會被自動運行.
但是,ngRoute需要進行配置后才可以正常工作
ngRoute的服務名叫做 route,其配置對象應該為 routeProvider
* 默認情況下,錨鏈接必須以#!開頭.
* 然后調用$routeProvider的when方法進行配置
* 第1個參數: 匹配到的hash值.hash值從#!后開始.
* 第2個參數: 匹配到以后,做什么事情.templateUrl要請求的資源路徑.
然后指定1個ng-view,表示將請求來的資源加到這個元素下.
<div class="container" ng-controller="demoCtrl"><ul><li><a href="#!/home">首頁</a></li><li><a href="#!/my">我的音樂</a></li><li><a href="#!/find">發現音樂</a></li></ul><div class="content" id="content" ng-view></div></div>路由配置
when方法的第2個參數說明
* templateUrl,代表要請求的資源的路徑.模板路徑.
* template, 字符串形式的模板.
* controller,模板與控制器建立聯系,建立起聯系后,就可以使用控制器操作視圖了.
* redirectTo,挑轉到其它路由.
* otherwise方法,如果所有的when都匹配不上,就otherwise
3.配置$locationProvider
hashPrefix方法,用來配置錨點值的前置符號.默認是嘆號!
當然我們可以自定義這個前置符號.
app.config(['$locationProvider',function ($locationProvider) {$locationProvider.hashPrefix('');//不設置前置 #/index//$locationProvider.hashPrefix('@');設置前置 #@/index}]);為什么默認哈希前置設置為!
- 如果網站內容是通過Ajax異步請求的.搜索引擎是看不到內容的.
- 如今單頁面應用比較受追捧,搜索引擎進行了升級.其也能夠獲得ajax異步的數據.比如Google
- 但是有個前提,通過地址上某些符號來分辨哪些網站是ajax異步的.谷歌認為#!是異步的.
4. 路由參數
QueryString參數不影響路由.
使用$routeParams服務,可以獲取路由參數.
在控制器視圖加載的時候,就會執行控制器代碼,在這個控制器中可以注入$routeParams服務,取到QueryString參數
<script>var app = angular.module('hmApp',['ngRoute']);app.config(['$routeProvider','$locationProvider',function ($routeProvider,$locationProvider) {$locationProvider.hashPrefix('');$routeProvider.when('/login',{templateUrl:'./login.html'}).when('/register',{templateUrl:'./register.html'}).when('/list',{templateUrl:'./list.html',controller:'listCtrl'}).otherwise({});}]);app.controller('listCtrl',['$scope','$routeParams',function ($scope,$routeParams) {//在控制器被加載的時候,加載這個視圖傳遞的QS參數,可以通過$routeParams服務拿到.$scope.lessons = ['html','css','js','java'];console.log($routeParams);}]);</script>5.路由參數的另外一種形式
寫在when方法的第一個參數上使用:參數的形式
when('/register/:id',{templateUrl:'./register.html',controller:'regCtrl' })那么在傳遞的時候, 使用這樣的格式 index.htlm#/register/4,控制器拿到的參數就是{id:”4”}
再比如使用如下的when參數
那么在傳遞的時候, 使用這樣的格式 index.htlm#/register/page/4,控制器拿到的參數就是{page:”4”}
需要注意的是,參數必須使用冒號:
比如:
when('/list/page/:page/name',{templateUrl:'./register.html',controller:'regCtrl' })那么在傳遞的時候, 使用這樣的格式 index.htlm#/list/page/4/name,控制器拿到的參數就是{page:”4”}
如果希望沒有值也能匹配到.加問號
jQuery Lite
- AngularJS不建議我們進行DOM操作.因為DOM的更新會隨著數據模型的變* 化而自動變化.
- 但是總會在某些時候,我們還是希望操作DOM的.
- AngularJS為我們封裝了一個輕量版的jQuery.
- 調用全局對象angular的一個element方法,可以將1個原生的DOM對象轉換為一個jQuery對象.
- 然后可以使用這個jQuery對象的方法進行DOM操作.
- 需要注意的是,這僅僅是Angular提供的一個輕量級的jq,所以僅僅是包裝了jq常用的方法.
- 如果我們的頁面上引入了jQuery庫,那么angular.element() 完全等價于 jQuery().
- 如果我們的頁面上沒有引入jQuery庫,那么就會使用ng內置的的一個迷你版本的jQuery,叫做jqLite。
- jqLite中只提供了常用的方法. 比如animate方法就沒有.
總結
以上是生活随笔為你收集整理的Angular的学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 揭秘“跨界程序猿”如何跨境卖文具?日单破
- 下一篇: turn