本文主要說明在用AngularJS開發web應用中如何實現lazyload,使用AngularJS需要在前端實現路由功能,本文就介紹利用此點實現前端資源的懶加載。
問題
目前大部分AngularJS的應用用requirJS組織模塊,但是很多都沒有使用lazyload功能,在app.js中啟動時將全部依賴加載進來,在模塊功能較少,前端資源少的情況下沒問題。那么問題來了,依賴資源過多時怎么辦?
- build時利用grunt-contrib-requirejs提取合並文件,減少http請求,但是存在問題:build后文件大;線上調試不方便,尤其在html2js后問題更明顯。
- 開發中盡量在原有文件里進行新業務添加,不增加額外的http請求壓力,但是存在問題:多人合作時需要經常處理代碼沖突;單個文件(control,directive等)很大,看的是眼花繚亂,容易出問題。
解決問題
基本思路:在路由切換時加載所需要資源。
工具:Angular-ui-router,oclazyload,requirejs。
- 配置oclazyload
在引入oclazyload文件后配置主要參數項app.config(['$ocLazyLoadProvider',function($ocLazyLoadProvider){ $ocLazyLoadProvider.config({ loadedModules: ['monitorApp'],//主模塊名,和ng.bootstrap(document, ['monitorApp'])相同 jsLoader: requirejs, //使用requirejs去加載文件 files: ['modules/summary','modules/appEngine','modules/alarm','modules/database'], //主模塊需要的資源,這里主要子模塊的聲明文件 debug: true }); }]);
- 配置ui-route
利用angularjs-ui-route配置路由跳轉的基本規則和需要懶加載文件app.config(['$stateProvider', '$urlRouterProvider',function($stateProvider, $urlRouterProvider){ var lazyDeferred; /** * 路由切換時調用 * @param param.file 懶加載文件數組 * @param tpl 子模塊view視圖 * @param module 子模塊名 */ function resovleDep(param,tpl,module){ var resolves = { loadMyCtrl: ['$ocLazyLoad', '$templateCache', '$q', function($ocLazyLoad,$templateCache,$q) { lazyDeferred = $q.defer(); return $ocLazyLoad.load({ name : module, cache: false, files: param.files }).then(function() { lazyDeferred.resolve($templateCache.get(tpl)); }); }] }; return resolves; }; $urlRouterProvider.otherwise('/summary'); //路由配置 $stateProvider .state('module1', { url:'/module1', templateProvider: function() { return lazyDeferred.promise; }, controller: 'module1Controller', resolve : resovleDep({files:[ 'controllers/module1Ctrl', 'services/module1Service', 'directives/module1Directive' ]}, 'views/module1.html', 'app.module1') }) .state('module2', { abstract: true, url: '/module2', templateUrl: 'views/module2.html' }) .state('module2.list', { url: '', templateProvider: function() { return lazyDeferred.promise; }, controller: 'module2Controller', resolve : resovleDep({files:[ 'controllers/module2ListCtrl', 'services/module2Service' ]}, 'views/list.html', 'app.module1') }) .state('module1.detail', { url: '/:id', templateProvider: function() { return lazyDeferred.promise; }, controller: 'detailController', resolve : resovleDep({files:[ 'controllers/detailCtrl', 'services/detailService' ]}, 'views/detail.html', 'app.module2') }); }]);
結束
ok,至此就可以在路由切換時方便的加載子模塊和依賴資源,oclazyload和ui-router還有很多可挖掘的,大家可參考api滿足需求。
ps:最初用angular-route+oclazyload做時出現:
multiple directives asking for isolated scope on
multiple asking for template
等問題,不好用,建議使用ui-route,強大的多。