首页 > 学院 > 开发设计 > 正文

Lazy Loading In AngularJS(懒加载)

2019-11-06 09:37:35
字体:
来源:转载
供稿:网友

当构建大型网站或应用程序在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文物实例对象。因此,为了登记一个懒惰的控制器,你可以使用controllerPRovider。同样的,要登记一个指令,你会用compileprovider美元,登记过滤器可以使用$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,在示例应用程序一看。请注意,但是,示例应用程序只是一个非常基本的(即,不生产质量)的例子。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表