Aangular作為前端開發利器,被廣大前端研發人員所熟知,本人從接觸到現在快有兩年時間了,負責和Angular相關的產品也有10幾個,有商務邏輯複雜的,有業務簡單的,業務簡單架構就簡單,怎麼搭建都行,只要開發效率快,維護成本低就可以,但是針對於複雜的商務邏輯,就會遇到很多問題,如果在初始化的時候進行互相依賴載入,那樣首次載入,如果使用angular-ui-router進行路由管理,就需要將所有state依賴的的controller檔案全部載入進來,由於業務複雜,controller檔案有可能會有很多,還不包括資源類的請求,這樣首次載入會非常緩慢,影響使用者體驗。
為瞭解決首次載入問題,首次載入只載入公用資源,並且將業務模組進行細化,每個路由狀態對應相應的業務模組,首次載入只提供給使用者的某一個模組,讓首次載入更加輕量化,其他業務模組在路由狀態切換時進行動態載入,也就是所謂的按需載入,最終選擇方引用第三方組件angularAMD和ct-ui-router-extras來解決。
angularAMD是實現angular的controller、service非同步載入的核心組件,ct-ui-router-extras是ui-router的擴充外掛程式, 進行狀態管理,它主要是監聽路由狀態變化,具體文檔大家可以戳這裡:http://christopherthielen.github.io/ui-router-extras/#/home,主要是用到其中的futureState,在應用啟動時候在config中對futureState進行初始化,將所有的路由狀態配置到 futureState中,在路由發生變化時,先判斷路由狀態是否存在,如果不存在,則會調用初始化時註冊的angularAMD的ngload服務,實現對模組以及依賴的非同步載入。
初始化配置
config(['$futureStateProvider','$locationProvider',function($futureStateProvider,$locationProvider) { var loadAndRegisterFutureStates = ['$http','lazyHerper',function ($http,lazyHerper) { return lazyHerper.getLazyModuleCfg().then(function(moduleCfg){ angular.forEach(moduleCfg, function (cfg) { $futureStateProvider.futureState(cfg); }); }); }]; $futureStateProvider.stateFactory('ngload', ngloadStateFactory); // register AngularAMD ngload state factory $futureStateProvider.stateFactory('iframe', iframeStateFactory); // register silly iframe state factory $futureStateProvider.stateFactory('requireCtrl', requireCtrlStateFactory); // Register state factory that registers controller via eval. $futureStateProvider.addResolve(loadAndRegisterFutureStates); }])
這個函數是按需載入的核心
function ngloadStateFactory($q, futureState) { var ngloadDeferred = $q.defer(); require([ 'ngload!' + futureState.src , 'ngload', 'angularAMD'], function ngloadCallback(result, ngload, angularAMD) { angularAMD.processQueue(); ngloadDeferred.resolve(undefined); }); return ngloadDeferred.promise; }
懶載入路由設定檔
define([],function(){
return {
lazyCfg:[
{
“stateName”:”app.cloud”,
“urlPrefix”:”/cloud”,
“type”:”ngload”,
“src”:globalConfig.appPath+’cloud/app-cloud.module.js’
},
{
“stateName”:”app.network”,
“urlPrefix”:”/network”,
“type”:”ngload”,
“src”:globalConfig.appPath+’network/app-network.module.js’
}
]
}
})
這裡有一點需要注意,就是在模組按需夾在的時候需要對響應的服務進行動態註冊,否則會提示不能註冊angular相關服務。
define([“utils/depResolve”],function(depResolve){
return function(routerConfig){
var self = this;
this.config([‘ stateProvider′,‘ stateProvider’, ‘urlRouterProvider’,
‘ locationProvider′,‘ locationProvider’, ‘controllerProvider’,
‘ compileProvider′,‘ compileProvider’, ‘filterProvider’,
‘ provide′,function( provide’, function(stateProvider, urlRouterProvider, urlRouterProvider, locationProvider, controllerProvider, controllerProvider, compileProvider, filterProvider, filterProvider, provide){
//多模組的非同步載入時,無法滿足模組controller、directive、service等動態定義
//也就是說在載入完module檔案後,再動態載入相關的controller、directive、service等時
//提示controller、directive、service等未定義
//所以必須在載入module檔案同時在模組的config中注入相應的provider服務進行動態註冊。
self.controller = controllerProvider.register;self.directive= controllerProvider.register; self.directive = compileProvider.directive;
self.filter = filterProvider.r