安裝VS2015 Update2的過程是非常曲折的。還好經過不懈的努力,終於折騰成功了。
如果開發Cordova項目的話,推薦大家用一下ionic這個框架,效果還不錯。對於Cordova、PhoneGap、ionic、AngularJS這些框架或庫的關系,我個人理解是這樣,PhoneGap是一個商業項目,用來實現HTML5式的跨平台開發,后來Adobe公司將其中的核心代碼開源,就是Cordova,Cordova只負責實現JavaScript調用原生代碼的功能,是一個殼,而殼里具體用什么樣式,在HTML5層還有很多框架,如ionic、jquery mobile都可以。ionic集成了AngularJS,實際上是寫了一些AngularJS的directive,用來簡化開發,ionic又提供了一套css樣式,如果開發web app,也可以只利用他的css樣式。VS2015對這些框架和類庫都提供了良好的支持。
雖然標題是UWP系列,但實際上我是以Android為第一平台寫這個demo的,因為還是想看看Cordova在Android平台的表現^_^ ionic已經支持Universal,所以本文最后我們也可以編譯成uwp應用來運行一下。
一、環境配置
我想做這樣一個最簡單的功能,顯示一個新聞列表,支持下拉刷新和滾動到底部自動加載更多。這是一個App最簡單的功能,在ionic里可以很簡單的實現。對於Angular的部分,我也會在開發過程中簡單介紹一下。
我學新東西的時候,不太喜歡先看很多概念的東西,而是先做個東西運行起來后,再去研究里面的概念。所以先建個項目運行一下看看吧。
Ionic主頁地址:http://ionicframework.com/
官方教程是以node.js的命令行來建立項目,還好有VS2015,可以直接下載ionic的項目模板來開始第一個項目。
ionic模板下載地址:https://visualstudiogallery.msdn.microsoft.com/4e44ba8b-a4c8-4106-b70e-00d63241a54a
Ionic智能感知支持下載地址:https://visualstudiogallery.msdn.microsoft.com/d6279fba-bcff-4857-906d-29faa8a99448/
也可以直接在VS2015的擴展里搜索ionic:
安裝前兩個即可,第一個是ionic的智能感知插件ionic Pack,第二個是ionic項目模板,支持三種樣式的項目,空白型、漢堡菜單型、Tab型。
二、新建項目
安裝好模板插件之后,新建一個Cordova項目IonicDemo,選Tabs Template:
接下來VS2015會下載很多包:
一定要保持網絡連接,不然很可能下載失敗。
嗯我有正常的網絡連接,還是失敗了……
三、項目結構
建好的項目是這樣的:
看一下項目結構,其實我們需要開發的主要部分都在www目錄里:
看,和一個簡單的web項目很像吧,css、img、js都有,這就是一個純HTML5的網站。Js目錄里是Angular的代碼,templates目錄里放的是頁面。
點開依賴項,發現有未安裝的部分:
不過不要緊,這個未安裝也不影響運行。
四、第一次編譯
現在插上你的安卓手機,運行第一個Cordova程序吧。在菜單上選擇調試設備,推薦用真機調試,我有次用了VS2015的安卓模擬器,速度是很快,但把網絡搞壞了。對於這種簡單的Cordova程序,用Ripple也是可以的。Ripple是在Chrome里運行的一個插件,也提供了一些比如GPS、后退鍵等模擬器的功能。
如果是第一次編譯Cordova項目,會下載Gradle,速度比較慢,大概需要半個多小時到更久。最好不要中途終止,不然會發生莫名其妙的錯誤。正常編譯一次后就快了。這是Ripple里的樣子:
左側是Ripple的一些信息,包括平台、版本、加速度計、電池狀態等,其中加速度計還可以模擬手機搖動的效果。
右側是設置、GPS信息、網絡、事件等
其中事件會經常用到:
這里提供了一些deviceready、backbutton等事件,其中deviceready是Cordova初始化完設備准備完畢后的事件,可以在里面做一些處理。Backbutton就是模擬后退鍵了。還可以提供pause、resume等事件的模擬。
不過對於目前這個簡單的程序來說,基本用不到那么復雜的功能,可以點擊Tab欄看看,三個Tab,首頁是一個介紹,第二個是一個聊天列表,第三個是一個開關按鈕。聊天列表點擊的時候還會有頁面切換效果,看着還不錯。
五、Angular的運行方式
接下來就該研究一下了,這些頁面是在哪里放着呢?又是怎么組裝起來的呢?
既然www目錄是個網站,當然首先要看看index頁面了。打開index.html頁面,可以看到,頁面頭部引入了ionic和Angular、Cordova的js文件,其中Cordova上面有一行注釋:
<!-- cordova script (this will be a 404 during development) -->
說明在開發過程中,這個文件找不到是正常的。
接下來有三行重要的js:
這就是核心的js文件了。Angular和MVC類似,也有model、controller等概念。
接下來是html代碼:
首頁就這么簡單,這些ion開頭的標簽,就是ionic提供的Angular的directive。Directive是Angular的重要概念,可以實現了自定義的html擴展。也就是說,ionic實際上是編寫了一套Angular的指令來實現這些漂亮的頁面效果。
如果沒接觸過Angular,可能還不太理解。沒關系,接着往下看。
打開www/js/app.js文件,這就是Angular的初始化文件:
看剛才的Index.html代碼,里面有
而js里有一個叫starter的module,這就把html和Angular聯系起來了。Angular看到ng-app的代碼,就會對這部分進行處理。module 函數有幾個參數,使用了依賴注入,注入了一個controller和一個services。
下面有config函數,這里使用了Angular的路由,來處理各種頁面的狀態:
也就是說,每個不同的state,對應不同的html頁面,使用不同的controller。
看tab頁,對應的template是tabs.html。打開:
這里又是ionic的指令,定義了三個ion-tab,來顯示不同的tab頁,對應不同的state。
再打開www/js/controller.js文件,里面就是各個controller的定義了:
這有點類似MVC的概念,每個頁面都有相應的controller處理。
接下來看Angular的一個重要概念,雙向綁定。我們剛才看聊天列表那個頁面,頁面地址是templates/ tab-chats.html,打開:
看ion-item里面有ng-repeat的代碼,這是Angular的循環,可以把后面的chat in chats循環顯示處理。那么chats是哪里來的呢?打開controller.js:
Controller里倒是有個chats,但$scope是啥東西?
我的理解,$scope是一個膠水,把controller和view粘起來。Controller里的東西,都要放在$scope下才能被view訪問到。ChatsCtrl里定義了一個$scope.chats,而頁面上就可以用
這樣的代碼,實現綁定。如果你寫過MVC或WPF程序,應該比較容易理解。
那么chats是哪里來的呢?ChatsCtrl首先進行了依賴注入,注入了一個Chats,然后函數里進行了一個賦值操作,Chats.all()
還記得剛才app.js里初始化app的時候注入了一個starter.services嗎?現在打開www/js/services.js:
找到了,services是定義在這里的。這里使用了Angular的factory,定義了一個名為Chats的factory,其中的all()方法就是返回一個聊天列表。
經過這樣的分析,我們就大概了解了程序的運行方式,首先Angular會初始化app,注入controller和service,對ionic的指令進行處理,渲染成頁面。
六、添加view及controller
現在可以考慮我們的目的了,我想添加一個tab頁,用來顯示一個新聞列表,這個列表也要從網絡接口進行獲取。
首先來添加一個tab頁。打開tabs.html,照貓畫虎加一個ion-tab:
圖標我偷懶就不改了,具體的圖標可參考:http://ionicons.com/ 這里有ionic自帶的圖標樣式
在templates目錄里添加一個tab-newsList.html文件。
在controller.js里,添加一個名為NewsListCtrl的controller:
在里面定義一個newsList,即要顯示的新聞列表。
現在修改app.js里的state,把controller和view關聯起來:
這樣在點擊新聞tab的時候,鏈接符合tab/newsList,就會找到NewsListCtrl的controller和tab-newsList.html,進行顯示。注意state里的各種參數,和view代碼的name的對應。
列表的樣子也是照着聊天的頁面寫:
好了,controller有了,view也有了,數據也定義了,但數據從哪來呢?當然要從網絡獲取了。
七、Angular使用promise實現異步的Service
為了方便演示,我使用了一個新聞網站的api接口:
http://app.thepaper.cn/clt/jsp/v3/nodeContList.jsp?n=25462&WD-UUID=864819028898243&pageidx=1
這個接口是一個GET請求,有三個參數,其中pageidx是頁數。
獲取數據的部分寫在哪呢?我們參考services里的Chats,寫在services里。注意,模板自帶的用了factory,但我這里用service。其實這兩個東西差不多,我習慣用service。具體的區別可以參考這個文章:http://www.ng-newsletter.com/25-days-of-angular/day-1 反正我感覺除了service可以自定義一些參數,作用都差不多。
打開services.js,添加以下代碼:
定義一個NewsService,注入$q和$http。因為獲取網絡數據是異步的,Angular里提供了promis的實現方式,通過調用$q.defer()來創建一個deferred實例,deferred有resolve、reject、notyfy幾個方法,其中resolve是接受結果,reject是拒絕。Promise有一篇文章寫的比較好:http://blog.jobbole.com/51178/現在只知道promise是用來實現異步的就可以了。$http是Angular內置的http服務,可以方便的實現get/post等各種網絡請求,用法和jQuery的ajax有點類似。
對了還得看一下接口的返回數據。瀏覽器可以直接請求那個地址,返回的數據是這樣的:
數據是json格式,如果resultCode為1,說明返回正常。contList是一個新聞標題的列表。
service里面這樣寫:
最后,要返回deferred.promise。
八、調用service顯示數據
Service返回的是一個promise,在調用的時候,會使用then方法來接收數據。Then方法有兩個參數,一個是成功后的處理,一個是失敗后的處理。修改controller里的代碼:
注意不要忘了把NewsService注入進來。
還要改一下頁面的項模板:
現在運行一下看看:
咦?Tab標題怎么亂碼了呢。這肯定是編碼問題了。
在tabs.html文件上點右鍵,選擇打開方式,選擇帶編碼功能的html編輯器:
然后選擇utf-8:
可以看到,果然亂碼了:
重新輸入中文標題,保存。現在就是utf-8編碼了。有可能VS2015在保存的時候選擇了GB2312。但這種情況沒找到規律,有時候文件中也有中文就沒錯。如果遇到編碼問題的話就手動改一下吧。
關於ion-list 的顯示樣式,可參考官方文檔,有更多說明:http://ionicframework.com/docs/components/#list
及http://ionicframework.com/docs/api/directive/ionList/
九、下拉刷新和滾動加載更多
列表展示出來了,現在加上下拉刷新和滾動到底部加載更多吧。
Ionic貼心的封裝了這兩個方法。下拉刷新是ionRefresher: http://ionicframework.com/docs/api/directive/ionRefresher/
加載更多是ion-infinite-scroll: http://ionicframework.com/docs/api/directive/ionInfiniteScroll/
先來看下拉刷新。在controller里添加以下代碼:
實際上下拉刷新就是重新獲取一下第一頁數據,把數據重新賦值即可。
然后修改view,修改tab-newsList.html文件,在ion-content里添加以下代碼:
對,就一個ion-refresher就搞定了。
加載更多也是類似,在controller里添加一個獲取更多的方法:
修改view:
注意,下拉刷新是加在ion-content指令的最前面,而加在更多是放在最后,都要被ion-content指令包裹起來。
是不是很簡單?想想uwp里的下拉刷新……
十、使用VS Code編輯代碼
順便說一下,我在使用ionic pack插件的時候,頻繁遇到了引起VS2015崩潰的問題,目前還沒找到好的解決辦法。其實可以用VS Code來編碼,安裝后按F1,輸入"擴展",對你沒看錯,要輸入中文!哈哈VS Code中文化的太徹底了。以前都是輸入ext install,現在必須輸入中文命令。然后找ionic和Angular的擴展安裝,就可以支持智能提示了。
VS Code寫代碼也是很爽的,ionic注釋都是中文的哈哈:
十一,跨平台
其實用Cordova主要還是為了跨平台,ionic也支持uwp啊,要不然我就不好意思寫成Win10 UWP開發系列了。在調試目標那里選一下,可以看到支持n個平台:
選Universal,連接個Win10手機,一樣能編譯運行哦^_^ 是這個樣子的:
可以看到,tab的位置在下面,跟Android平台是不一樣的。Ionic根據各平台的設計語言進行了定制。但也可以通過配置項來更改。
iOS因為沒有設備,沒有條件測試了。
如果有無法編譯或無法安裝的情況,可以試試清理解決方案,再重新編譯即可。我遇到過幾次,都是清理后就可以安裝調試了。
結語
這個demo到這里就結束了。查看新聞詳情的頁面跟查看聊天詳情的步驟一樣,就不寫了。這個例子主要是想說明,VS2015對Cordova的支持已經很完善了。這只是一個很簡單的入門例子,更深入的內容我也在逐步學習。希望有興趣的同學一起討論。還有很重要的一點,對於跨平台App開發我一直有這個觀點,跨平台不是萬能的,要看具體的使用場景。比如簡單的新聞瀏覽app,可以用Cordova方式,如果涉及到較多調用硬件的場景,還是原生代碼效率更高。現在也可以試試Xamarin,VS2015 Update2已經內置了Xamarin的支持,期待以后Xamarin有更好的表現。