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