Lazy Loading In AngularJS(懒加载)

当构建大型网站或应用程序在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,在示例应用程序一看。请注意,但是,示例应用程序只是一个非常基本的(即,不生产质量)的例子。

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

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
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GY程序源

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值