AngularJS簡(jiǎn)介:AngularJS 是一個(gè)為動(dòng)態(tài)WEB應(yīng)用設(shè)計(jì)的結(jié)構(gòu)框架,提供給大家一種新的開(kāi)發(fā)應(yīng)用方式,這種方式可以讓你擴(kuò)展HTML的語(yǔ)法,以彌補(bǔ)在構(gòu)建動(dòng)態(tài)WEB應(yīng)用時(shí)靜態(tài)文本的不足,從而在web應(yīng)用程序中使用HTML聲明動(dòng)態(tài)內(nèi)容。
AngularJS有五個(gè)主要核心特性,如下介紹:
雙向數(shù)據(jù)綁定—— 實(shí)現(xiàn)了把model與view完全綁定在一起,model變化,view也變化,反之亦然。
模板—— 在AngularJS中,模板相當(dāng)于HTML文件被瀏覽器解析到DOM中,AngularJS遍歷這些DOM,也就是說(shuō)AuguarJS把模板當(dāng)做DOM來(lái)操作,去生成一些指令來(lái)完成對(duì)view的數(shù)據(jù)綁定。
MVVM—— 吸收了傳統(tǒng)的MVC設(shè)計(jì)模式針但又并不執(zhí)行傳統(tǒng)意義上的MVC,更接近于MVVM(Moodel-View-ViewModel)。
依賴注入—— AngularJS擁有內(nèi)建的依賴注入子系統(tǒng),可以幫助開(kāi)發(fā)人員更容易的開(kāi)發(fā),理解和測(cè)試應(yīng)用。
指令—— 可以用來(lái)創(chuàng)建自定義的標(biāo)簽,也可以用來(lái)裝飾元素或者操作DOM屬性
ionic簡(jiǎn)介: ionic是一個(gè)強(qiáng)大的_混合式/hybrid_HTML5移動(dòng)開(kāi)發(fā)框架,特點(diǎn)是使用標(biāo)準(zhǔn)的HTML、 CSS和JavaScript,開(kāi)發(fā)跨平臺(tái)(目前支持:Android、iOS,計(jì)劃支持:Windows Phone、Firefox OS) 的原生App應(yīng)用。
ionic主要包括三個(gè)部分:
CSS框架- 提供原生_App質(zhì)感的CSS樣式模擬_。ionic這部分的實(shí)現(xiàn)使用了ionicons圖標(biāo)樣式庫(kù)。
JavaScript框架- ionic基于AngularJS基礎(chǔ)框架開(kāi)發(fā),遵循AngularJS的框架約束;主要提供了適應(yīng)移動(dòng)端UI的 AngularJS的擴(kuò)展,主要包括指令和服務(wù)。此外,ionic使用AngularUI Router來(lái)實(shí)現(xiàn)前端路由。
命令行/CLI- 命令行工具集用來(lái)簡(jiǎn)化應(yīng)用的開(kāi)發(fā)、構(gòu)造和仿真運(yùn)行。ionic命令行工具使用了 Cordova,依賴于平臺(tái)SDK(Android & iOS)實(shí)現(xiàn)將移動(dòng)web項(xiàng)目打包成原生app。
由于ionic使用了HTML5和CSS3的一些新規(guī)范,所以要求iOS7+/Android4.1+。 在低于這些版本的手機(jī)上使用ionic開(kāi)發(fā)的應(yīng)用,有時(shí)會(huì)發(fā)生莫名其妙的問(wèn)題。
安裝ionic/Install Ionic
首先您需要安裝Node.js. 其次, 安裝最新版本的cordova 和 ioniccommand-line tools. 通過(guò)參考Android和iOS官方文檔來(lái)安裝.
npm install -g cordova ionic
通過(guò)Ionic創(chuàng)建一個(gè)項(xiàng)目
使用Ionic官方提供的現(xiàn)成的應(yīng)用程序模板,或一個(gè)空白的項(xiàng)目創(chuàng)建一個(gè)Ionic應(yīng)用。
ionic start myApp blank ?創(chuàng)建一個(gè)空白的app項(xiàng)目 (下圖1)
ionic start myApp tabs 創(chuàng)建一個(gè)帶有tabs項(xiàng)目(下圖2)
ionic start myApp sidemenu 創(chuàng)建一個(gè)帶有滑動(dòng)的項(xiàng)目(下圖3)
我現(xiàn)在創(chuàng)建一個(gè)空白的項(xiàng)目 ionic start myApp blank
然后我們看到有myApp項(xiàng)目生成。如下目錄
然后我們用瀏覽器打開(kāi)index就可以看的如下圖的東西了。
接著下一步,我們用編輯器打開(kāi)index.html。觀察里面所引入的文件,我的習(xí)慣把跟項(xiàng)目無(wú)關(guān)的文件刪除了。你可以不刪除,我也改動(dòng)了部分文件的位置,之所以叫你觀察里面引入的文件,就是怕你刪錯(cuò)了,項(xiàng)目啟動(dòng)不了。改動(dòng)完結(jié)構(gòu)如下:
其中配置文件,controller,driectives,filter,services,文件都是我新建的。
下面先從app.js說(shuō)起
這個(gè)myApp需要在根節(jié)點(diǎn)啟動(dòng)。一個(gè)項(xiàng)目建議一個(gè)這樣的模塊。
上述路由config配置是基于ui-router,因?yàn)樵趇ndex.html已經(jīng)引入了ionic.bundle.min.js文件,這個(gè)文件把a(bǔ)ngular.js和ui-router及ionic所需的組件都幫我們打包好了,所以引用很方便。
打開(kāi)這個(gè)ionic.bundle.min.js看一下就知道合成了什么東西了,如圖:
把6個(gè)文件包合成一個(gè)了,你可以分別百度看看各是什么包,留給你們思考。
$stateProvider.state(name, {
? ? url: '',
? ?templateUrl:'', // 這個(gè)是模板位置
? ?controller: '' // 這個(gè)是對(duì)應(yīng)模板的controller名稱!記住是名稱不是位置
});
上述是ui-router的基本用法,詳情用法可以去查看官方文檔。
app.js配置完,下面就配置controller
剛才我們配置完了app.js,我們要新建一個(gè)名字叫homeCtrl的controller。命名我建議XXXCtrl或者XXXController,當(dāng)然以你們項(xiàng)目為標(biāo)準(zhǔn)。
采用閉包的模式創(chuàng)建controller,為了保險(xiǎn)防止不必要變量污染的錯(cuò)誤。其中
angular.module('myApp') 就是載入剛才創(chuàng)建的模塊,然后設(shè)置一個(gè)叫做homeCtrl的controller,
格式一般都是angular.module('myApp').controller(name, [params, function(params) {}])。
創(chuàng)建完成homeCtrl之后呢,在index.html中引用,如下圖:
好了,我們根據(jù)剛才配置的路由創(chuàng)建完了controller,現(xiàn)在就差模板了。
創(chuàng)建home模板
在剛才創(chuàng)建文檔template文件夾當(dāng)中,新建一個(gè)home.html。也就是剛才配置app.js中的路由中寫的路徑和名字,忘記的回頭看看app.js是怎樣寫的。在剛才創(chuàng)建的home.html,寫上以上內(nèi)容
如下圖:
在項(xiàng)目中我們這樣寫著,凡是帶有<ion-xxx></ion-xxx>都是ionic框架自帶的。這是一個(gè)指令,如果你還不明白指令什么意思,沒(méi)關(guān)系。你就當(dāng)做一個(gè)帶有某些功能的自定義標(biāo)簽。
創(chuàng)建home.html模板和homeCtrl.js之后。我們?cè)囍鴨?dòng),在瀏覽器中打開(kāi)index.html這個(gè)文件,這個(gè)文件作為一個(gè)項(xiàng)目的入口。ion-view就是這個(gè)頁(yè)面的頂層,所有內(nèi)容都在這個(gè)view中,ion-header就是那個(gè)頭部,ion-content就是內(nèi)容。這些都不是必須的,但是我建議這樣寫,因?yàn)閕onic有些組件是需要在這些標(biāo)簽里面才能起作用的。然后看到如下圖:
當(dāng)看到頁(yè)面和控制臺(tái)都出現(xiàn)“hello world”文字,證明我們成功了,項(xiàng)目啟動(dòng)成功。
創(chuàng)建app.js和html模板及homeCtrl模板總結(jié)
其實(shí)我們寫項(xiàng)目的思路:舉剛才那個(gè)例子
1、創(chuàng)建一個(gè)app.js,首先能啟動(dòng)項(xiàng)目,然后配置路由。其中路由需要模板和controller那么問(wèn)題來(lái)了,接著看2、3、步。
2、然后創(chuàng)建模板,XXX.html模板。
3、最后創(chuàng)建XXXCtrl.js的controller。
編寫控制器與模板
下面來(lái)點(diǎn)有意思的吧,先來(lái)個(gè)輪播圖。那就用ionic框架自帶的吧,具體查文檔即可,如下圖:
刷新瀏覽器如下圖:
好了,這證明我們成功了,可以滑動(dòng),可以自帶切換。其實(shí)還有很多功能,可以查閱文檔嘗試。一般由于手機(jī)網(wǎng)站banner都是從后臺(tái)讀取數(shù)據(jù)的,那么我們來(lái)改寫。在controller獲取數(shù)據(jù),然后賦值給$scope變量,由于頁(yè)面和對(duì)應(yīng)controller的$scope有關(guān)聯(lián),所以對(duì)應(yīng)頁(yè)面上的屬性也會(huì)變好,是不是還是不太明白,那么來(lái)看代碼吧。homeCtrl如下:
我們把代碼改成
1、ng-repeat="item in views.slideData track by $index",意思就是從$scope.views.slideData數(shù)組遍歷,item是數(shù)組里面的某一項(xiàng),track by $index其實(shí)是性能優(yōu)化,后續(xù)會(huì)講,你也可以不寫直接ng-repeat="item in views.slideData"
2、之前由<img src="路徑"> 這種變成 ?<img ng-src="{{item}}",其中ng-src是一個(gè)angular自帶的指令,item是數(shù)組遍歷出來(lái)的路徑
從服務(wù)器獲取數(shù)據(jù)
啰嗦的話不說(shuō)了,直接上案例。如圖:
既然要數(shù)據(jù),那么先建一個(gè)服務(wù),使用 angular.module 的 factory API創(chuàng)建服務(wù),是最常見(jiàn)也是最靈活的方式。其實(shí)還有幾種
factory()
service()
constant()
value()
provider()
,具體詳情查文檔,不過(guò)多數(shù)項(xiàng)目用這種(factory)創(chuàng)建方法就滿足需求了。舉個(gè)簡(jiǎn)單例子
factory() 方法是創(chuàng)建和配置服務(wù)的最快捷方式。 factory() 函數(shù)可以接受兩個(gè)參數(shù)。
name (字符串)
需要注冊(cè)的服務(wù)名。
getFn (函數(shù))
這個(gè)函數(shù)會(huì)在AngularJS創(chuàng)建服務(wù)實(shí)例時(shí)被調(diào)用。
angular.module('myApp')
? ?.factory('myService', function() {
? ? ? ?return {
? ? ? ? ? ?'username': 'auser'
? ? ? ?};
? ?});
要上我們真實(shí)的示例代碼了哦,如下圖:
有同學(xué)覺(jué)得奇怪了,怎么會(huì)是app.factory呢?其實(shí)app就是angular.module('myApp',[]),我在app.js文件里面把a(bǔ)ngular.module('myApp',[])賦值給全局變量app了。見(jiàn)下圖:
我們建好了servers。在index.html里面引入哦:
好!創(chuàng)建好servers.js,還有在index中引入。那么怎么在controller中調(diào)用呢?那我們來(lái)看看改寫后的controller,如圖:
我們創(chuàng)建services到調(diào)用services里面的ajax請(qǐng)求都成功了,如何在homeCtrl中獲取數(shù)據(jù)呢?
那就先從services改寫開(kāi)始,如下圖:
homeCtrl怎么獲取數(shù)據(jù)?看下圖:
調(diào)用myFactory.getList()方法為什么后面還跟著一個(gè)then的。其實(shí)我們使用內(nèi)置的 $http 服務(wù)直接同外部進(jìn)行通信。 $http 服務(wù)只是簡(jiǎn)單的封裝了瀏覽器原生的 XMLHttpRequest 對(duì)象。$http 服務(wù)是只能接受一個(gè)參數(shù)的函數(shù),這個(gè)參數(shù)是一個(gè)對(duì)象,包含了用來(lái)生成HTTP請(qǐng)求的配置內(nèi)容。這個(gè)函數(shù)返回一個(gè)promise對(duì)象, 由于 $http 方法返回一個(gè)promise對(duì)象,我們可以在響應(yīng)返回時(shí)用 then 方法來(lái)處理回調(diào)。如果使用 then 方法,會(huì)得到一個(gè)特殊的參數(shù),它代表了相應(yīng)對(duì)象的成功或失敗信息,還可以接受兩個(gè)可選的函數(shù)作為參數(shù)。或者可以使用 success 和 error 回調(diào)代替,至于promise對(duì)象是什么,這里就不一一敘述了,寫起來(lái)篇幅比較大,還是留給你們查文檔吧。
promise.then(function(resp){
// resp是一個(gè)響應(yīng)對(duì)象
}, function(resp) {
// 帶有錯(cuò)誤信息的resp
});
// 或者使用success/error方法
promise.success(function(data, status, headers, config){
// 處理成功的響應(yīng)
});
// 錯(cuò)誤處理
promise.error(function(data, status, headers, config){
// 處理非成功的響應(yīng)
});
然后看看控制臺(tái)輸出什么,還是看圖:
OK!大功告成,我們可以把這些數(shù)據(jù)綁定在$scope上,然后渲染到頁(yè)面。還是看圖:
總結(jié):
1、創(chuàng)建services并寫好里面的服務(wù),然后在index.html引入services。
2、homeCtrl中注入依賴services里面的factory服務(wù),調(diào)用里面的方法。
3、在homeCtrl調(diào)用factory服務(wù)方法,然后獲取數(shù)據(jù)。再把數(shù)據(jù)賦值給$scope。所以模板也能獲取$scope里面的數(shù)據(jù),那么頁(yè)面數(shù)據(jù)就更新了。
編寫過(guò)濾器
上面已經(jīng)教會(huì)大家如何建立一個(gè)services服務(wù)獲取數(shù)據(jù),但是有時(shí)候我們獲取數(shù)據(jù)回來(lái)的數(shù)據(jù)做進(jìn)一步修改顯示在頁(yè)面,下面假如我們有一個(gè)需求,我想把姓名全部變成大寫。
1、首先創(chuàng)建一個(gè)filter。
2、在index.html引入filter。(這個(gè)不說(shuō)了,請(qǐng)看上面services怎么引入的)
在home.html頁(yè)面中,姓名這樣寫。
姓名:{{item.Name | toUpperCaseText}}
那么我現(xiàn)在想把城市變成小寫,怎么弄?留給你們一個(gè)作業(yè)吧。
正如前面所見(jiàn),創(chuàng)建自定義過(guò)濾器非常容易。創(chuàng)建自定義過(guò)濾器需要將它放到自己的模塊中。過(guò)濾器本質(zhì)上是一個(gè)會(huì)把我們輸入的內(nèi)容當(dāng)作參數(shù)傳入進(jìn)去的函數(shù)。上面只是一個(gè)簡(jiǎn)單的例子,其實(shí)就是把數(shù)據(jù)獲取進(jìn)來(lái),數(shù)據(jù)進(jìn)來(lái)了,你想怎樣處理數(shù)據(jù)就怎樣處理。相當(dāng)于你小時(shí)候,你騙你爸爸媽媽零用錢的時(shí)候,錢到你口袋了,至于錢怎么用了,那是你自己的事。當(dāng)你爸爸媽媽問(wèn)你拿去干什么的時(shí)候,你告訴他了,那就相當(dāng)于把數(shù)據(jù)處理完渲染在頁(yè)面了。過(guò)濾器其實(shí)內(nèi)置有很多很好用的,需要的時(shí)候時(shí)不時(shí)的查看文檔就行了。用法就是這么簡(jiǎn)單。
過(guò)濾器總結(jié)
1、分析需求怎樣的數(shù)據(jù)在頁(yè)面,查閱內(nèi)置過(guò)濾器是否滿足需求。
2、假如需求內(nèi)置過(guò)濾器不能滿足,創(chuàng)建filter.js,編寫處理數(shù)據(jù)邏輯。
3、在index.html引入過(guò)濾器。在需要用過(guò)濾器的加上“|”,例如:{{item.Name | toUpperCaseText}}
頁(yè)面之間傳遞數(shù)據(jù)
當(dāng)我們寫完home.html頁(yè)面并且完成了homeCtrl,及通過(guò)services獲取后臺(tái)服務(wù)器的數(shù)據(jù),展示到頁(yè)面,證明我們成功了一個(gè)小項(xiàng)目的大部分。你可以想象,一個(gè)項(xiàng)目都是獲取數(shù)據(jù),展示數(shù)據(jù)(至于怎樣展示,點(diǎn)擊展示還是默認(rèn)展示,這是交互性的東西),或者提交數(shù)據(jù),提交數(shù)據(jù)本文并沒(méi)有說(shuō),但是我們已經(jīng)知道怎樣獲取了,提交還困難么。都是差不多的原理。自己翻閱文檔看看$http的方法就可以解決了。我們下面繼續(xù)實(shí)現(xiàn)一個(gè)需求,點(diǎn)擊剛才的某一項(xiàng)列表,跳到詳情頁(yè)。
新建一個(gè)詳情頁(yè)detail.html,新建一個(gè)detailCtrl的控制器,并且配置詳情頁(yè)路由。忘記了的可以看看前面新建home的步驟。(記得在index.html引入detailCtrl哦,否則會(huì)報(bào)下面的錯(cuò),看圖)
下面展示路由配置及detail.html頁(yè)面和detailCtrl.js
我們配置完路由和新建detail的頁(yè)面及controller。我們實(shí)現(xiàn)點(diǎn)擊列表跳轉(zhuǎn)到detail頁(yè)面,并帶上數(shù)據(jù)。我再啰嗦一次,本文帶有<ion-xxx>都是ionic框架自帶的,ion-view就是這個(gè)頁(yè)面的頂層,所有內(nèi)容都在這個(gè)view中,ion-header就是那個(gè)頭部,ion-content就是內(nèi)容。這些都不是必須的,但是我建議這樣寫,因?yàn)閕onic有些組件是需要在這些標(biāo)簽里面才能起作用的。
那我們點(diǎn)擊列表
思路就是ng-click="views.goDetail(item)"; views.goDetail就是跳轉(zhuǎn)到detail頁(yè)面,跳轉(zhuǎn)路由使用$state.go("XXX");XXX代表路由的名稱,item就是你點(diǎn)擊某一項(xiàng)的數(shù)據(jù),看圖:
我們點(diǎn)擊列表的時(shí)候既可以,可以看到console把item的內(nèi)容打印出來(lái)。
現(xiàn)在需求要實(shí)現(xiàn)下面的詳情圖。
如何實(shí)現(xiàn)從A頁(yè)面==》B頁(yè)面,并且把A頁(yè)面的數(shù)據(jù)帶到B頁(yè)面。下面來(lái)探討angular頁(yè)面之間的傳遞數(shù)據(jù)方式。下面講5種方法,可能有更多,但是我選常用的講。
1、可以用$rootScope頂級(jí)作用域,從A頁(yè)面賦值給$rootScope的某個(gè)屬性,然后B頁(yè)面獲取數(shù)據(jù)賦值到頁(yè)面。
結(jié)果,如大家所愿詳情頁(yè)能實(shí)現(xiàn)剛才的效果了。
2、在A頁(yè)面用$state.go("xxx", {obj});配置路由參數(shù),然后在B頁(yè)面用$stateParams對(duì)象獲取url的參數(shù)。
使用這個(gè)方法從home頁(yè)面?zhèn)鬟f過(guò)來(lái)的url
3、在services里面建立一個(gè)服務(wù),在A頁(yè)面把數(shù)據(jù)傳遞給這個(gè)服務(wù),然后在B頁(yè)面獲取這個(gè)服務(wù)的值。為什么可以這樣做?因?yàn)閟ervices服務(wù)里面的方法是共享的,當(dāng)項(xiàng)目初始化的時(shí)候services已經(jīng)實(shí)例化了一次(服務(wù)是一個(gè)單例對(duì)象,在每個(gè)應(yīng)用中只會(huì)被實(shí)例化一次(被 $injector 實(shí)例化),并且是延遲加載的(需要時(shí)才會(huì)被創(chuàng)建)),所以不存在跳轉(zhuǎn)頁(yè)面就數(shù)據(jù)沒(méi)了。(這個(gè)是最佳實(shí)踐哦,不過(guò)也要看業(yè)務(wù)場(chǎng)景。這個(gè)是我最常用的)。
頁(yè)面之間的傳遞數(shù)據(jù),以上是常用的3種。下面介紹沒(méi)那么常用的:
利用localStorage、sessionStorage、cookie在A頁(yè)面中存值,然后在B頁(yè)面中獲取值,這3個(gè)都是可以存儲(chǔ)數(shù)據(jù)。他們之間的區(qū)別你們查文檔吧,哈哈哈~~~~ 留給你們思考。
數(shù)據(jù)綁定
數(shù)據(jù)綁定,從剛一開(kāi)始從服務(wù)獲取數(shù)據(jù),然后把數(shù)據(jù)綁定到$scope上,然后在頁(yè)面輸入{{}}花括號(hào)輸出,這種就是數(shù)據(jù)綁定了。那我們來(lái)個(gè)假設(shè),現(xiàn)在有個(gè)輸入框,輸入框是多少,列表中的那個(gè)人的年齡是多少。
由于這個(gè)需求,就是雙向數(shù)據(jù)綁定,可以ng-model用綁定一個(gè)變量,這個(gè)變量賦值給年齡,那么年齡也跟著變了。看下圖:
好啦好啦,初始化做完了。下面呢,我們?cè)趇nput輸入框值,改變一下input框里面的值,看看有什么變化。
改變了
輸入框里面的值改變了,上面的年齡值也改變了。證明$scope.views.age的值改變了,這些就是數(shù)據(jù)綁定了。
數(shù)據(jù)綁定總結(jié)
當(dāng)AngularJS認(rèn)為某個(gè)值可能發(fā)生變化時(shí),它會(huì)運(yùn)行自己的事件循環(huán)來(lái)檢查這個(gè)值是否變“臟”。如果該值從上次事件循環(huán)運(yùn)行之后發(fā)生了變化,則該值被認(rèn)為是“臟”值。這也是Angular可以跟蹤和響應(yīng)應(yīng)用變化的方式。這個(gè)事件循環(huán)會(huì)調(diào)用$digest()循環(huán)(這個(gè)你們查查文檔就能知道了)。這個(gè)過(guò)程被稱作臟檢查(dirty checking)。臟檢查是檢查數(shù)據(jù)模型變化的有效手段。當(dāng)有潛在的變化存在時(shí),AngularJS會(huì)在事件循環(huán)時(shí)執(zhí)行臟檢查(查閱文檔)來(lái)保證數(shù)據(jù)的一致性。
源碼:百度網(wǎng)盤 http://pan.baidu.com/s/1i59P1cD
假如你打開(kāi)了源碼。我寫得比較丑別笑話我,里面或許有一些錯(cuò)誤,望指正,假如我有空可以交流一下。
假如你看到源碼會(huì)報(bào)這些錯(cuò),第一個(gè)錯(cuò)是因?yàn)槲也](méi)有引入cordova進(jìn)去,第2/3/4報(bào)錯(cuò)是因?yàn)閏ss源碼的字體丟失了。(問(wèn)題在home頁(yè)的輪播的小圈圈,其實(shí)你可以寫樣式把它干掉,問(wèn)題即可解決)