ngLazyLoad——让ng项目实现controllers按需异步加载

最初的源码来自:https://github.com/atian25/angular-lazyload/

但由于一些个人的原因(我有强迫症...)所以把代码的书写风格按照我平日的喜好修改了下

也顺便认真的阅读了一遍源码,按照自己的理解,把原来的英文注释替换成中文的了

毕竟不是原作者,对ng框架也不是特别的熟,注释中的用词可能有不少不正确的地方,欢迎指出

下面是我稍微修改了一下的代码:

/*
* angular-lazyLoad
* 一个angular项目的按需异步加载服务模块
* 支持 [Sea.js](http://seajs.org/) & [RequireJS](http://requirejs.org/‎)
*/
(function() {
    ‘use strict‘;
    //定义 angular-lazyLoad 模块 & $lazyLoad 服务
    angular.module(‘ngLazyLoad‘, [], [‘$controllerProvider‘, ‘$compileProvider‘, ‘$filterProvider‘, ‘$provide‘,
        function ($controllerProvider, $compileProvider, $filterProvider, $provide) {
            //定义 $lazyLoad 服务
            $provide.factory(‘$lazyLoad‘, [‘$rootScope‘, ‘$q‘, function($rootScope, $q){
                /*
                *  在代码的运行后,你是无法使用 app.controller(...) 方式来定义控制器的
                *  只能通过 $controllerProvider.register 方法来定义控制器
                *  定义一个 register 对象缓存这些低阶方法,在构造 $lazyLoad 服务对象时作为参数传入
                * */
                var register = {
                    controller: $controllerProvider.register,
                    directive: $compileProvider.directive,
                    filter: $filterProvider.register,
                    factory: $provide.factory,
                    service: $provide.service,
                    decorator: $provide.decorator
                };

                return new LazyLoadProvider($rootScope, $q, register);
            }]);
        }
    ]);

    /**
     * $lazyload 服务类
     */
    function LazyLoadProvider($rootScope, $q, register){
        var _this = this;
        _this.$$rootScope = $rootScope;
        _this.$$q = $q;
        _this.register = register;

        //为 $rootScope 添加 safeApply 方法
        _this.patchScope();
    }

    /**
     * @param {Object} app 需要异步添加控制器的app主模块
     * @param {Function/String} loader 加载器类型,取值范围如下:
     *   - ‘seaJS‘ : 默认值,使用 seaJS 去异步加载模块
     *   - ‘requireJS‘: 使用 requireJS 去异步加载模块
     *   - {Object} : 自定义加载器,此对象应该包含下面两个属性:
     *     - check {Function} 检测方法,检测路由切换后,是否需要异步加载模块
     *     - load {Function} 加载方法,应该包含三个参数:当前路由对象(用来获取controllerUrl属性的值),加载成功回调,加载失败回调
     */
    LazyLoadProvider.prototype.init = function(app, loader){
        //根据loader参数,来决定用什么加载器
        var _this = this,
            _loader = angular.isObject(loader) ? loader : this.loaders[loader] || this.loaders[‘seaJS‘];

        //给app主模块添加register,以便可以使用低阶方法定义控制器
        app.register = _this.register;

        //监听 $routeChangeStart 事件
        _this.$$rootScope.$on(‘$routeChangeStart‘, function(event, curRoute){
            var route = curRoute && curRoute.$$route;

            if(route){
                if(typeof _loader.check == ‘function‘ && _loader.check(route)){
                    route.resolve = route.resolve || {};

                    /*
                     * 关键点:使用route的resolve对象
                     * 每当路由变更时,angular都会遍历route的resolve对象的各个属性
                     * 如果某个是指向一个函数,那么该函数就会被马上执行
                     */
                    route.resolve.loadedModule = function(){
                        var defer = _this.$$q.defer();

                        _loader.load(route,
                            function(module){
                                _this.$$rootScope.safeApply(function(){
                                    defer.resolve(angular.isFunction(module) ? module(app) : module);
                                });
                            },
                            function(module){
                                _this.$$rootScope.safeApply(function(){
                                    defer.reject(module);
                                });
                            });

                        return defer.promise;
                    };
                }
            }
        });
    };

    //为 $rootScope 增加 safeApply 方法, 安全的apply
    LazyLoadProvider.prototype.patchScope = function(){
        var _this = this;

        _this.$$rootScope.safeApply = function(fn){
            var phase = this.$root.$$phase;
            if(phase == ‘$apply‘ || phase == ‘$digest‘){
                if(fn && (typeof(fn) === ‘function‘)){
                    fn();
                }
            }else{
                this.$apply(fn);
            }
        };
    };

    LazyLoadProvider.prototype.loaders = {};

    LazyLoadProvider.prototype.loaders[‘seaJS‘] = {
        check: function(route){
            //当存在 controllerUrl 属性,且其类型为字符串时,路由变更后才执行异步加载方法
            return typeof route.controllerUrl == ‘string‘
        },
        load: function(route, suc, fail){
            seajs.use(route.controllerUrl, function(module){
                if(angular.isUndefined(module)){
                    fail(module);
                }else{
                    suc(module);
                }
            });
        }
    };

    LazyLoadProvider.prototype.loaders[‘requireJS‘] = {
        check: function(route){
            //当存在 controllerUrl 属性,且其类型为字符串时,路由变更后才执行异步加载方法
            return typeof route.controllerUrl == ‘string‘
        },
        load: function(route, suc, fail){
            require(route.controllerUrl, function(module){
                if(angular.isUndefined(module)){
                    fail(module);
                }else{
                    suc(module);
                }
            });
        }
    };
})();

使用方法和原作也有一丝丝区别,其实只是省去了一行代码,这里也搬一下吧~

1.将代码引入到你的项目页面中去(下面几个基本上可以说是必备的了)

<script src="libs/angular.js"></script>
<script src="libs/angular-route.js"></script>
<script src="libs/angular-lazyLoad.js"></script>
<script src="libs/sea.js" id="seajsnode"></script>

2.手动执行angular.bootstrap

seajs.use("app", function(app){
  angular.bootstrap(document, ["app"]);
});

3.将ngLazyLoad添加到你的主模块依赖中去

var app = angular.module("app", ["ngLazyLoad", "ngRoute"]);

4.在app.run方法中初始化

app.run(["$lazyLoad", function($lazyLoad){
  $lazyLoad.init(app);
  ...
}]);

5.路由映射中,添加controllerUrl属性

$routeProvider
  .when("/login", {
    controller: "loginCtrl",
    controllerUrl: "js/controllers/login.js",
    templateUrl: "app/templates/login.html"
});

6.在你的模块里,通过 app.register.controller 方法来定义控制器

define(function(require, exports, module){
  "use strict";

  module.exports = function(app){
    app.register.controller("loginCtrl", ["$scope", function($scope){      ...    }]);
  }
}
时间: 2024-12-11 07:28:52

ngLazyLoad——让ng项目实现controllers按需异步加载的相关文章

Eclipse项目发布到Tomcat下被加载两次

近来发现,Eclipse项目发布到Tomcat下被加载了两次.启动Tomcat时,项目被加载了两次,项目启动了两次. 启动tomcat会两次加载项目 原因是server.xml设置的问题. 解决方案:在右边的工程中,有一个Servers 这里有个server.xml文件,打开,观察文件最末尾, 删除Context标签.注意不要把</Host>也删了. 改后,如下所示(即还剩一个</Host>标签):

vs2012打开低版本项目时 出现vs2012警告未能加载包“visual c++ package 解决办法

vs2012 打开 vs2010 项目时 提示的 错误信息. 解决办法 是下载一个 vs2012的 一个补丁包 http://www.microsoft.com/en-us/download/details.aspx?id=36020 初次安装成功后,调试 无法启用,关闭,重新打开项目 即可解决! ======ok. [在此谢谢网上提供解决方案的朋友们,谢谢你们!] vs2012打开低版本项目时 出现vs2012警告未能加载包"visual c++ package 解决办法

如何按需动态加载js文件

JavaScript无非就是script标签引入页面,但当项目越来越大的时候,单页面引入N个js显然不行,合并为单个文件减少了请求数,但请求的文件体积却很大.这时候最好的做法就是按需引入,动态引入组件js和样式,文件load完成后调用callback,运行js.代码还是很简便的.塔河县臧清机械 1. 判断文件load完成.加载状态ie为onreadystatechange,其他为onload.onerror 01 if(isie){ 02     Res.onreadystatechange =

【原创】从零开始搭建Electron+Vue+Webpack项目框架(五)预加载和Electron自动更新

导航: (一)Electron跑起来(二)从零搭建Vue全家桶+webpack项目框架(三)Electron+Vue+Webpack,联合调试整个项目(四)Electron配置润色(五)预加载及自动更新(六)构建.发布整个项目(包括client和web)(未完待续) 摘要:到目前为止,我们的项目已经具备了PC客户端该有的一些基础功能和调试环境,但是总感觉缺了灵魂,那就是结合实际项目.实际业务的细节处理,缺着吧...这篇文章就介绍一下预加载和自动更新,文字功底有限,如有介绍的不清楚的地方,欢迎留言

.net MVC项目启动失败, 先自动加载再自动卸载

从之前的项目拷贝了一个,在此基础上删掉不用的部分,修改掉所有命名空间及文件名之后就成了一个新项目. 然而,启动失败. 并且没有报错,LOG中也没有,只看到输出先是自动加载了一堆dll,突然间又自动卸载了. 后来想到是因为web.config中打开了customErrors, 把它重新设置为off之后,错误显示出来了.  程序集"Yc.Oms.Web"中发现的引用启动类型"Yc.Oms.Web.Startup"的 OwinStartup 属性与程序集"Yc.

IDEA Maven项目找不到或无法加载主类

IDEA导入项目运行时出现 错误: 找不到或无法加载主类 的问题 清除缓存并重启 重启完成后执行Maven clean 最后执行Maven compile 重新编译项目,问题解决 原文地址:https://blog.51cto.com/acevi/2470511

swift项目第四天:动态加载控制器

一:Appdelegate import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { /* 总结: 1:1:window为可选类型,可选类型的定义:var window: UIWindow?,可选类型就是可以为空值nil或是有值,若是想获得可选类型的值,则可以进行可选绑定或是强制解包,若是强制解包必须要保证强制解包的值不为nil,若为nil会产生崩溃,一般可选绑定用guard e

VS2012创建WebForm项目提示错误: 此模板尝试加载组件程序集 “NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”。

解决方案: 使用VS2012开发,都要装NuGet插件(官网:http://nuget.org),进官网点安装就进入了微软的下载页面, 选择vs2012版本的NuGet.Tools.vsix文件,双击安装就可以了.下载地址如下: https://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c

项目用到异步加载头像LasyList

package com.leo.proforjob; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Handler; import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ExecutorSer