AngularJs應用頁面切換最佳化方案
葡萄城的一款尚在研發中的產品,對外名稱暫訂為X項目。其中使用了已經上市的wijmo中SpreadJS產品,另外,在研發過程中整理了一些研發總結分享給大家。如本篇的在頁面切換的過程中最佳化方案,歡迎大家跟帖交流。 前言AngularJs被用來開發單頁面應用程式(SPA),利用AJAX調用配合頁面的局部重新整理,可以減少頁面跳轉,從而獲得更好的使用者體驗。Angular的ngView及其對應的強大路由機制,是實現SPA應用的核心模組。本文所說的頁面切換指的就是這個路由機制,即根據不同的url展示不同的視圖。 有一種非常常見的情境:在切換至新頁面後,需要通過AJAX調用從伺服器請求一些資料,然後根據這些資料來展示頁面。如果未做任何處理,那麼頁面會先載入新頁面的html模版,但此時模板中的資料model還並沒有被請求,因此會有一段時間顯示空資料,非常影響使用者體驗。 情境讓我們以Angular官方給出的 PhoneCat Tutorial App來說明這個問題。 在PhoneCat項目的github首頁上有這麼一段話:“There is no dynamic backend (no application server) for this application. Instead we fake the application server by fetching static json files.”也就是說,這個樣本項目中只是類比了一個server,所以當頁面請求phones.json和每個手機的詳細資料時,這些請求會在非常短的時間內就完成了,我們並感覺不到展示頁面存在什麼問題。 而在真實的網路環境中,請求這些json檔案可能會消耗相對較長的時間。讓我們來類比一下網路請求回應時間較長的情況。在這裡我用了express來代替原來的http-server,並在用戶端請求資料時延遲5秒再做出響應: image 運行起來後可以看到,頁面立即會顯示出來,但是原本應該顯示手機列表的地區是一片空白,直到5秒之後才將列表資料顯示出來。點擊一個手機名稱進入詳細資料頁面,同樣是一開始只顯示了html模板的內容,然後才將參數資料填充到頁面上。過程中頁面會出現抖動,非常影響使用者體驗。 使用resolve來提前請求資料在遇到這個問題時,我最先想到的就是添加一個loading提示:在網路請求前顯示loading遮罩圖片,網路請求結束後再將其隱藏。於是點擊進入手機的detail頁面後頁面會呈現一個loading圖片,像這樣: clip_image002 可以看到,頁面應該顯示手機詳細資料的地區顯示空白,造成非常不好的使用者體驗。這是因為PhoneDetailCtrl的代碼是在頁面跳轉寄生後才執行的,而此時手機資訊資料還沒有從伺服器擷取到,也就是說$scope.phone這個model還未被賦值。有沒有一種辦法讓這些資料在切換到這個頁面之前就先準備好呢? 答案當然是有,也就是這篇文章要介紹的主角——resolve。我們知道ng-view是通過$routeProvider來訂製頁面路由規則,這個路由規則在phonecat項目源碼中是這樣定義的: image為了讓頁面跳轉之前執行一些事情,我們可以在路由規則中配置resolve參數。 Resolve參數可以注入一組service到路由綁定的controller之中。如果其中的一個或多個service是非同步對象($q.defer)時,那麼只有當這些非同步作業都完成後,頁面才會跳轉。利用這一點,我們就可以在頁面跳轉前先將手機詳細資料資料請求到本地。跳轉後,目標頁面就會立即正常顯示資料。 我將手機詳細資料頁面的路由配置代碼修改如下: image在上面的代碼中,我只能使用$route.current.params來擷取phoneId參數,因為此時頁面還未跳轉,$routeParams是擷取不到任何值的。經過這樣配置resolve參數後,我就可以在PhoneDetailCtrl中注入一個名為phoneDetailsService的對象。PhoneDetailCtrl的代碼如下: image這樣,就可以在頁面跳轉之前擷取到請求的資料了。 為頁面加入切換動畫為了讓頁面間的切換更平滑,可以在頁面切換加入過渡動畫。AngularJs對一些常用的指令比如ngRepeat、ngSwitch以及ngView都有動畫的支援。 AngularJs通過CSS來定義動畫,要實現DOM元素的動畫效果非常簡單。當DOM元素變化的時候,AngularJs會在元素上添加特定的class: · ng-enter,當元素被添加時會被應用; · ng-move,當元素被移動時會被應用; · ng-leave,當元素被刪除時會被應用。 我們可以對ng-view應用AngularJs動畫,在phone-cat項目中,animation.css中的下列代碼實現了切換頁面的淡入淡齣動畫: .view-frame.ng-enter,.view-frame.ng-leave { background: white; position: absolute; top: 0; left: 0; right: 0;} .view-frame.ng-enter { -webkit-animation: 0.5s fade-in; -moz-animation: 0.5s fade-in; -o-animation: 0.5s fade-in; animation: 0.5s fade-in; z-index: 100;} .view-frame.ng-leave { -webkit-animation: 0.5s fade-out; -moz-animation: 0.5s fade-out; -o-animation: 0.5s fade-out; animation: 0.5s fade-out; z-index: 99;} 總結在Web應用中,為了獲得良好的使用者體驗,就要在介面上使用一些技巧讓使用者不會感覺到突兀。本文提出了兩點技巧讓AngularJs應用在頁面切換時更加自然平滑。