zoukankan      html  css  js  c++  java
  • 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]

  • 相关阅读:
    laravel 连接同一服务器上多个数据库操作 、 连接多个不同服务器上的不同数据库操作以及多个数据库操作的事务处理
    061——VUE中vue-router之通过程序控制路由跳转
    015PHP文件处理——文件处理flock 文件锁定 pathinfo realpath tmpfile tempname
    linux传输文件lrzsz
    ffmpeg命令详解(转)
    提取文件名剔除扩展名
    CGI = MCC + MNC + LAC + CI
    VMware虚拟机提示“锁定文件失败 打不开磁盘”解决方法
    VirtualBox.org
    bat函数调用 带返回值
  • 原文地址:https://www.cnblogs.com/ywang/p/7418634.html
Copyright © 2011-2022 走看看