angularjs + ionic 實現項目的按需加載


參考:

ionic入門教程第十六課-在微信中使用ionic的解決方案(按需加載加強版)作者有一系列的ionic教程,很不錯!

AngularJS模塊詳解

 

自己的demo:

angularjs-ionic-demo 

demo中的READE.md寫的比較混亂,可以忽略不看

ionic自帶使用gulp壓縮文件可以查看gulpfile.js文件(里面有我添加的基本task,要使用gulp還要安裝相應依賴項哦!),至於項目只看www文件就可以了

 

背景:

一開始使用angularjs+ionic做項目,並沒有什么經驗,只能是把東西拼湊在一起,能完成任務就行。但是做到后面發現,在首頁一進去加載的時候所有的東西都會被一次性加載出來,這就導致加載時間很長。

當項目需求開始趨於穩定的時候,決定重做項目:按需加載頁面,樣式和js

 

開始按需加載:

這里就不贅述項目的生成等過程了,簡單的使用Ionic Lab就可以創建3種不同的項目

1、在app.js中定義懶加載服務

當然要在首頁引入ocLazyLoad.min.js,這一點兒別忘記

var app = angular.module('starter', ['ionic', 'oc.lazyLoad'])

 

2、設置所有的js文件(控制器,自定義指令,過濾器等)都支持按需加載

.config(['$stateProvider', '$ionicConfigProvider','$urlRouterProvider', '$controllerProvider', '$compileProvider', '$filterProvider', '$provide', '$ocLazyLoadProvider', "$locationProvider", 'JS_REQUIRES',
    function($stateProvider,$ionicConfigProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide, $ocLazyLoadProvider, $locationProvider, jsRequires) {
  // 主要代碼(框架自帶的懶加載的解決方案)
   app.controller
= $controllerProvider.register; app.directive = $compileProvider.directive; app.filter = $filterProvider.register; app.factory = $provide.factory; app.service = $provide.service; app.constant = $provide.constant; app.value = $provide.value; $stateProvider ...// 路由等代碼 }]);
// JS_REQUIRES是自定義的在配置表里面定義的,算是靜態變量
 

 3、配置表文件(實現js和css的按需加載),在項目中我命名為config放在js文件夾下,記得在首頁中引用該文件

'use strict';

// 使用$provide.constant來定義了一個靜態變量(見app.js中的config的配置)
app.constant('JS_REQUIRES', {
    //*** Scripts
    scripts: {
        //*** Controllers
        'TestCtrl':"js/controllers/TestCtrl.js",
        //*** Services
        'HttpService':"js/services/HttpService.js"
        //*** Filter
        'SetDataTimeFilter': "js/filter/SetDataTimeFilter.js",
        //*** Directive
        'StarDirective': "js/directive/Star.js",
        //*** 第三方
        // 復制文本到剪貼板
        'clipboard': "js/other/clipboard.min.js",
    },
    CssArg:{
      TestStyle: 'css/test.css',
    },
  // 把業務員相關聯的文件按照界面寫成分組,這樣在代碼中就不用把太多的精力放在文件關聯上 ViewArgs: { TestArgs: [
'TestCtrl', 'HttpService', 'SetDataTimeFilter', 'TestStyle'] } });

 

4、拆分js文件

在www/js下新建controllers(控制器)、services(服務)、directive(指令)、filter(過濾器)等文件

以TestCtrl文件(controller)為例:

‘use strict’; // 使用嚴格模式

app.controller('TestCtrl', ["$scope", function(){
   ...
}]);

// 這里使用的app.controller其實是使用了$controllerProvider.register

 

相應的:

services文件使用app.factory

directive文件使用app.directive

filter文件使用app.filter

4、使用oclazyload和$q的組合實現動態加載文件

.config(['$stateProvider', '$ionicConfigProvider','$urlRouterProvider', '$controllerProvider', '$compileProvider', '$filterProvider', '$provide', '$ocLazyLoadProvider', "$locationProvider", 'JS_REQUIRES',
    function($stateProvider,$ionicConfigProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide, $ocLazyLoadProvider, $locationProvider, jsRequires) {
    
    //第一步的配置代碼

  //配置路由 $stateProvider .state('test', { url: '/test', templateUrl: 'templates/test.html', prefetchTemplate:false, // 不會提前加載html(實現html頁面的按需加載) controller: 'TestCtrl', resolve: loadSequence('TestArgs') /* 只關聯少量文件時,可以寫上所有的文件【loadSequence('ChatsCtrl','ChatsService')】; 或者文件比較多的時候,寫上關聯的模塊名稱 */ $urlRouterProvider.otherwise('/home'); function loadSequence() { var _args = arguments; // 傳不傳參數都能匹配到 var viewArgs = repeatArgs(_args[0]); //先匹配模塊的,沒有再匹配單文件的 if(viewArgs){ // 先匹配模塊,找到就把模塊對應的單文件列表返回給它,找不到就當做是單文件列表 _args = viewArgs }else{ //console.log("沒有找到模塊?") } function repeatArgs(name){ return jsRequires.ViewArgs[name]; } return { // 使用oclazyload和$q的組合實現懶加載 deps: ['$ocLazyLoad', '$q', function ($ocLL, $q) { var promise = $q.when(1); for (var i = 0, len = _args.length; i < len; i++) { promise = promiseThen(_args[i]); } return promise; function promiseThen(_arg) { if (typeof _arg == 'function') return promise.then(_arg); else return promise.then(function () { var nowLoad = requiredData(_arg); if (!nowLoad) return console.log('找不到文件 [' + _arg + ']'); return $ocLL.load(nowLoad); }); } function requiredData(name) { if (jsRequires.modules) for (var m in jsRequires.modules) if (jsRequires.modules[m].name && jsRequires.modules[m].name === name) return jsRequires.modules[m]; if(jsRequires.scripts && jsRequires.scripts[name]){ return jsRequires.scripts[name]; }else if(jsRequires.CssArg && jsRequires.CssArg[name]){ return jsRequires.CssArg[name]; } // return jsRequires.scripts && jsRequires.scripts[name]; } }]};} })

 

 

 

到此,我們想要的基本實現了。首次加載的時候只加載需要的文件,切換頁面再加載其他文件。后面自行添加具體的功能就可以了

 

5、壓縮

可以使用gulp壓縮文件到一個單獨的文件夾,記得把lib和index.html文件放進去。直接把訪問地址中的www改成相應的名稱就可以了。

前端構建工具gulpjs的使用介紹及技巧

 

 

了解angularjs,主要針對上面的第二步進行講解,如果對代碼沒有問題可忽略

1、模塊

angular模塊通過angular.module(name, requires, configFn)方法生成:

  • 參數name是模塊名稱;
  • 參數requires標識依賴模塊數組。如果不設置requires參數,調用angular.module(name)方法表示獲取這個模塊;因此,如果確定新模塊沒有依賴關系,必須設置requires為空數組[];
  • 參數configFn是方法或數組,負責在模塊初始化時做一些配置,如果是數組,最后一個元素必須是方法

已經初始化的angular模塊保存在一個叫modules的緩存對象中,key是模塊名,value是模塊對象。所以,定義一個同名的模塊,等於覆蓋之前的模塊

2、服務注入

angular模塊只保留服務的定義。

服務提供商,在Angular中稱為Provider,幾乎所有的服務(除了$injector)都是由服務提供商供應。無論是服務還是服務提供商,他們在Angular中都是唯一的,服務和服務提供商是一個一對一的關系。

所以整個過程:

  • 模塊定義服務、服務提供商;
  • 注入器根據模塊依賴關系加載模塊,實例化所有服務提供商;
  • 應用需要服務,注入器根據服務名尋找服務提供商,服務提供商實例化服務;

每個angular模塊內置有三個數組:

  • invokeQueue保存如何注入服務提供商和值的信息;
  • configBlocks保存模塊的配置信息;
  • runBlocks保存這個模塊的執行信息

模塊被使用的時候,注入器根據invokeQueue中的信息,實例化服務提供商;根據configBlocks中的信息對服務提供商做一些額外的處理;根據runBlocks中提供的信息,調用前面的服務提供商提供的服務執行模塊需要完成的工作。

angular模塊提供了很多方法來填充這三個數組,比如config()、run()等。

例如:添加一個Controller:

angular.module('ngAppDemo',[])  
.controller('ngAppDemoController',function($scope) { $scope.a= 1; $scope.b = 2; });

這段代碼等於:

invokeQueue.push(['$controllerProvider','register', ['ngAppDemoController', function(){}]]);

注入器根據這個信息,就會調用$controllerProvider的register方法注冊一個ngAppDemoController.

同理:

constant()

給默認的$provider注冊一個常量:

原理:在invokeQueue首部插入['$provide', 'constant', arguments]。

controller()

在$controllerProvider中注冊一個控制器:

原理:在invokeQueue尾部插入['$controllerProvider', 'register', arguments]。

directive()

在$compileProvider中注冊一個指令:

原理:在invokeQueue尾部插入['$compileProvider', 'directive', arguments]

factory()

生成一個服務工廠(隱式創建一個了服務提供商):

原理:在invokeQueue尾部插入['$provide', 'factory', arguments]

filter()

在$filterProvider中注冊一個過濾器:

原理:在invokeQueue尾部插入['$filterProvider', 'register', arguments]

service()

注冊一個服務(隱式創建了一個服務提供商):

原理:在invokeQueue尾部插入['$provide', 'service', arguments]

value()

注冊一個變量(隱式創建了一個服務提供商):

原理:在invokeQueue尾部插入['$provide', 'value', arguments]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM