Lazy Loading In AngularJS(懒加载)

来源:互联网 发布:音频算法工程师 编辑:程序博客网 时间:2024/05/26 14:08

当构建大型网站或应用程序在AngularJS许多/观点的路线,它将不会加载所有的文件,如控制器、指令等是很好的,在第一次加载。理想情况下,在第一次加载,只有文物所需要的路线的问题,将加载。这可能是在一个下载或多取决于应用程序,但是,它只会是什么需要渲染特定的路由。当用户导航App改变路线,其他文物尚未加载,将被加载时需要有。这种潜力不仅应该加快初始页面的负载,而且还应该导致带宽不被浪费。这个帖子,我的目的是展示的文物如控制器和指令可以实现与AngularJS的懒加载。
为了延迟加载的文物如AngularJS控制器和指示,有两个主要问题,必须回答如下:
1、如何在应用启动后,对一个模块进行懒加载的注册
2、在应用程序中,如何选择脚本加载的实际位置

第一个问题的结果从当前无法注册文物后,应用程序引导,使用模块API。换句话说,如果你想与一个已经自举程序登记一个新的控制器,使用下面的代码:

angular.module('app').controller('SomeLazyController', function($scope){    $scope.key = '...';});

you would get the following error when you reference the controller with the ng-controller directive:

Error: Argument ‘SomeLazyController’ is not a function, got undefined

目前,唯一的方法(我知道)登记的文物已经引导应用程序,不使用模块的API,但使用有关的AngularJS提供者代替。
供应商基本上是被用来创建和配置的AngularJS文物实例对象。因此,为了登记一个懒惰的控制器,你可以使用controllerprovidercompileprovider美元,登记过滤器可以使用$filterprovider,并登记等服务,你会使用提供服务。代码将看起来像这样的控制器和指令:

// Registering a controller after app bootstrap$controllerProvider.register('SomeLazyController', function($scope){   $scope.key = '...'; });// Registering a directive after app bootstrap$compileProvider.directive('SomeLazyDirective', function(){    return {        restrict: 'A',        templateUrl: 'templates/some-lazy-directive.html'    }})// etc

现在与供应商的事情是,他们只有在模块配置。因此,一个参考他们将不得不保持,以便他们可以用来以后登记懒惰文物。作为一个例子,为了获得相关的供应商,您可以设置您的应用程序模块类似以下:

appModule.js:(function(){    var app = angular.module('app', []);    app.config(function($routeProvider, $controllerProvider, $compileProvider, $filterProvider, $provide)    {        app.controllerProvider = $controllerProvider;        app.compileProvider    = $compileProvider;        app.routeProvider      = $routeProvider;        app.filterProvider     = $filterProvider;        app.provide            = $provide;        // Register routes with the $routeProvider    });})();

You would then be able to define a lazy controller as follows:

angular.module('app').controllerProvider.resgister('SomeLazyController', function($scope){    $scope.key = '...';});

仍然存在的问题,但是,在那里加载的懒惰文物,如上述控制器,将发生使用您的脚本加载器的选择。目前,只有一个地方,这可以发生“干净”,它是在“解决”属性的路由定义。
当定义一个路由使用routeprovider美元,你可以指定一个可选的关键/工厂地图的依赖,应注入路由控制器。使用“解决”属性指定此依赖关系图如下:

$routeProvider.when('/about', {templateUrl:'views/about.html', controller:'AboutViewController' resolve:{key:factory}

依赖映射中的“键”将是依赖项的名称,而“工厂”将是一个字符串,该字符串是作为依赖项的现有服务的别名,或作为其依赖项的返回值的可注入函数。现在,如果函数返回一个承诺,承诺将得到解决之前的路线是“渲染”(可以这么说)。因此,必须检索异步的依赖,如延迟加载的文物,可以使用一个依赖图的函数返回的承诺,将一次解决懒惰的文物已被加载的检索。这确保了所有的懒惰文物加载之前的路线呈现。一个路由定义中指定要使用的懒惰依赖美元script.js脚本加载器加载的一个例子,如下:

$routeProvider.when('/about', {templateUrl:'views/about.html', resolve:{deps:function($q, $rootScope){    var deferred = $q.defer();    var dependencies =    [        'controllers/AboutViewController.js',        'directives/some-directive.js'    ];    // Load the dependencies    $script(dependencies, function()    {        // all dependencies have now been loaded by so resolve the promise        $rootScope.$apply(function()        {            deferred.resolve();        });    });    return deferred.promise;}}});

有一件事,也应该指出的是,由于承诺的决议将最有可能的AngularJS的上下文之外发生的,如在上面的例子中,它在scriptjs美元背景下发生的,AngularJS已经被明确告知当诺言已经解决(这么说)。这是通过承诺内的应用方法$rootscopeas在实现:

$rootScope.$apply(function(){    deferred.resolve();});

如果承诺不解决在应用$rootscope,将不会对初始页面加载渲染。
现在所有这些应用程序模块定义,将产生以下:

appModule.js:(function(){    var app = angular.module('app', []);    app.config(function($routeProvider, $controllerProvider, $compileProvider, $filterProvider, $provide)    {        app.controllerProvider = $controllerProvider;        app.compileProvider    = $compileProvider;        app.routeProvider      = $routeProvider;        app.filterProvider     = $filterProvider;        app.provide            = $provide;        // Register routes with the $routeProvider        $routeProvider.when('/', {templateUrl:'views/home.html'});        $routeProvider.when('/about', {templateUrl:'views/about.html', resolve:{deps:function($q, $rootScope)        {            var deferred = $q.defer();            var dependencies =            [                'controllers/AboutViewController.js',                'directives/some-directive.js'            ];            $script(dependencies, function()            {                // all dependencies have now been loaded by $script.js so resolve the promise                $rootScope.$apply(function()                {                    deferred.resolve();                });            });            return deferred.promise;        }}});    });})();

Finally you can bootstrap the app using code similar to the following if using $script.js:

$script(['appModule.js'], function(){    angular.bootstrap(document, ['app'])});

这些都或多或少地要在AngularJS实现懒加载的步骤。总之,您将首先定义应用程序模块以保持相关提供商的实例。然后,您将定义您的懒惰的文物登记自己使用的供应商,而不是模块的API。然后使用一个“解析”函数返回你的路由定义中的一个承诺,你将加载所有的懒惰的文物和解决的承诺,一旦他们已经加载。这将确保所有的懒惰文物将提供相关的路线之前呈现。另外,别忘了解决承诺内rootscope美元。美元的申请,如果该决议将在AngularJS发生的事情。然后,您将创建一个“引导”的剧本,第一次加载的应用程序模块,在引导程序。最后,你会链接到你的索引HTML文件的启动脚本。
看到一个Runnable实例使用异步模块定义与RequireJS,在示例应用程序一看。请注意,但是,示例应用程序只是一个非常基本的(即,不生产质量)的例子。

以上都是废话,直接看代码:

html:<!DOCTYPE html><html ng-app="app"><head>    <meta charset="utf-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1">    <title></title> <script src="main/js/angular.min.js"></script> <script src="main/js/angular-route.min.js"></script> <script src="main/js/script.min.js"></script> <script src="main/js/app.js"></script></head><body><a href="#/about" title="">about</a><a href="#/home" title="">home</a><a href="#/alterplaplan" title="">alterplaplan</a><div ng-view></div></body></html>js:var app = angular.module('app', ["ngRoute"]);app.config(["$routeProvider", "$controllerProvider", "$compileProvider", "$filterProvider", "$provide",function($routeProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {    app.controllerProvider = $controllerProvider;    app.compileProvider = $compileProvider;    app.routeProvider = $routeProvider;    app.filterProvider = $filterProvider;    app.provide = $provide;    // Register routes with the $routeProvider    $routeProvider.when('/home', {        templateUrl: 'ClassReallot/html/home.html'    });    $routeProvider.when('/about', {        templateUrl: 'main/html/about.html',        resolve: {            deps: function($q, $rootScope) {                var deferred = $q.defer();                var dependencies =                    [                        'ClassReallot/js/courseController.js'                    ];                $script(dependencies, function() {                    $rootScope.$apply(function() {                        deferred.resolve(dependencies);                    });                });                return deferred.promise;            }        }    });    $routeProvider.when('/alterplaplan', {        templateUrl: 'ClassReallot/html/alterplaplan.html',        resolve: {            deps: function($q, $rootScope) {                var deferred = $q.defer();                var dependencies =                    [                        'ClassReallot/js/courseController.js'                    ];                $script(dependencies, function() {                    $rootScope.$apply(function() {                        deferred.resolve(dependencies);                    });                });                return deferred.promise;            }        }    });}]);
0 0
原创粉丝点击