利用寒假的時間給我家女神作了一個WebApp做爲情人節禮物,一爲表表忠心,二爲練練手,在過程當中也發現一些問題,在此總結總結。這裏面除了angular方面的問題,還有一些單頁面應用開發過程當中的問題。javascript
WebApp第一個版本完成以後興高采烈的打開瀏覽器測試,結果Chrome的加載時間讓我大跌眼鏡,整整用了八秒鐘的時間首頁在顯示出來,這明顯是不可接受的。因此必須進行拆分加載。整個WebApp分爲一個首頁和三個功能模塊,因此很天然把三個模塊拆分出來,優先加載首頁,在點擊導航的時候再依次加載對應模塊代碼。
功能模塊的延遲加載實際上就是與功能有關的控制器,服務和路由的延遲加載,因此在拆分加載中遇到的問題就是來自這些方面。首先經常使用的module.controller
的controller定義方式沒法知足App啓動以後的controller動態定義,也就是說若是在angular啓動了App以後再使用module.controller
的方式定義controller是無效的,仍然會報controller undefined的錯誤。這時候就須要使用$controllerProvider
的register
方法來動態定義controller。功能模塊的異步加載天然而然想到了requirejs
,具體實現以下:html
javascriptvar meng = angular.module('meng',['ionic','ngRoute']) ; //異步加載功能模塊 var resolveController = function(names){ return { loadController : ['$q','$rootScope',function($q,$rootScope){ var defer = $q.defer() ; require(names,function(){ defer.resolve() ; $rootScope.$apply() ; }) ; return defer.promise ; }] } } ; //route config meng.config( ['$routeProvider','$controllerProvider','$provide','$compileProvider', function($routeProvider,$controllerProvider,$provide,$compileProvider){ meng.register = { controller: $controllerProvider.register, factory: $provide.factory, directive: $compileProvider.directive }; $provide.decorator('$route',function($delegate){ var $route = $delegate ; $route.when = function( path, route ) { $routeProvider.when( path, route ); return this ; }; return $route ; }) ; $routeProvider .when('/',{ templateUrl : 'views/main.html' }) .when('/info',{ templateUrl : 'views/info.html' }) .when('/task',{ templateUrl : 'views/task/task.html', controller : 'taskController', resolve : resolveController(['TaskModule']) }) .when('/wallet',{ templateUrl : 'views/wallet/wallet.html', controller : 'walletController', resolve : resolveController(['WalletModule']) }) .when('/note',{ templateUrl : 'views/note/note_list.html', controller : 'noteController', resolve : resolveController(['NoteModule']) }) .otherwise('/'); }]) ;
上面的實現的關鍵就是resolveController
方法,它在路由過程當中利用require方法去加載功能對應的模塊代碼,在代碼加載完成後進行路由跳轉。上面省略了require的配置部分,TaskModule
,WalletModule
,NoteModule
分別對於task.js,wallet.js和note.js三個文件。
上面代碼中還解決了延遲加載中的另外一個問題,angular中路由配置是經過$routeProvider
完成的,可是這個服務在config的時候才能獲取,在App啓動以後是沒法獲取進行路由配置的,而$route
對象是隨時均可以獲取的,因此這裏在config過程當中對利用angular提供的裝飾方法對$route
進行了擴展,增長了一個when方法指向$routeProvider
的when
方法,這樣就能夠在其餘地方對路由進行配置。
經過上面的方法進行加載拆分有一個問題,它並無很好的利用angular中模塊化的特性,爲了延遲加載功能不得不把原來分爲三個module的代碼都合併到一個module中,這樣破壞了模塊的獨立性,如何在angular的module上進行延遲加載我還在尋找方法。java
高響應是單頁面應用的一大優點,這是由於單頁面應用會盡量少的刷新頁面。除了經過減小刷新來提升響應之外,減小沒必要要的數據交互也是一個關鍵。而爲了減小沒必要要的數據交互,對數據進行緩存是頗有必要的。在首次請求數據返回以後,將數據緩存下來,在下一次請求數據是先在緩存中查找,若是沒有再去請求服務器數據,在這個過程當中咱們必需要保證緩存的數據與服務器數據保持同步,因此在進行增刪改的時候須要同時對本地和服務器的數據進行增刪改。而我在開發過程當中把這部分功能實現放在Model中,這樣向上隱藏內部的數據層實現。在數據緩存這方面你們若是有更好的辦法,歡迎交流。promise
HTML5中的ApplicationCache離線存儲是一個很好的提升App加載速度的途徑,可是它也會給開發過程當中帶來一些不便,常常出現更新資源可是沒有更新manifest文件帶來的失誤,並且但願更新生效須要進行兩次頁面刷新,這是比較不方便的。因此這個東西好用確實好用,只是加入離線存儲應該放在開發過程的最後,在完成功能實現的前提下再把ApplicationCache加上去,這樣能夠避免它給開發過程當中帶來的不便。瀏覽器
上面所說的三個問題只是目前遇到的主要的三個問題,App還在改進中。對於angular的使用還不夠熟練,對於單頁面中的組織結構劃分和模塊化的理解還不夠透徹,除了上面所說的問題之外還有幾個問題有待繼續鑽研,好比如何更高效的處理數據緩存,移動設備上點擊的擊穿現象,還有CSS動畫的問題,總之就是多動手多思考少吃零食多睡覺。
PS:作了這個App以後發現本身真是不適合作設計,改了又改界面才勉強達到我家女神的要求,再接再礪吧。緩存