码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-02-20 20:49:03      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:

最初的源码来自: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){
      ...
    }]);   } }

 

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

标签:

原文地址:http://www.cnblogs.com/czf-zone/p/4296676.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!