Skip to content

Angular动态加载controller #13

@HuarenYu

Description

@HuarenYu

使用angular做单页应用时,如果页面很多,需要把很多controller打包到一起,但是经常用到的controller可能也就几个,这样会影响加载速度,如何实现按需加载controller呢?

配置ngRoute的时候有一个resolve参数,这个参数可以在控制器初始化之前给控制器注入一些依赖,如果是promise的话,会等等promise resolve后在注入,可以利用这个原理动态的加载js。

实现代码如下:

<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
    <meta charset="UTF-8">
    <title>angular</title>
</head>
<body>
    <div class="container" ng-view></div>
    <script src="https://cdn.staticfile.org/angular.js/1.6.0/angular.js"></script>
    <script src="https://cdn.staticfile.org/angular.js/1.6.0/angular-route.js"></script>
    <script src="https://cdn.staticfile.org/jquery/3.1.1/jquery.js"></script>
    <script>
        var app = angular.module ('app', ['ngRoute']);

        app.config(['$routeProvider', '$controllerProvider', function($routeProvider, $controllerProvider){

        app.registerCtrl = $controllerProvider.register;

        function loadScript(path) {
          var result = $.Deferred(),
          script = document.createElement("script");
          script.async = "async";
          script.type = "text/javascript";
          script.src = path;
          script.onload = script.onreadystatechange = function (_, isAbort) {
              if (!script.readyState || /loaded|complete/.test(script.readyState)) {
                 if (isAbort)
                     result.reject();
                 else
                    result.resolve();
            }
          };
          script.onerror = function () { result.reject(); };
          document.querySelector("head").appendChild(script);
          return result.promise();
        }

        function loader(arrayName){

            return {
              load: function($q){
                        var deferred = $q.defer(),
                        map = arrayName.map(function(name) {
                            return loadScript('js/controllers/'+name+".js");
                        });

                        $q.all(map).then(function(r){
                            deferred.resolve();
                        });

                        return deferred.promise;
                }
            };
        }

        $routeProvider
            .when('/', {
                templateUrl: 'views/foo.html',
                resolve: loader(['foo'])
            })
            .when('/bar',{
                templateUrl: 'views/bar.html',
                controller: 'BarCtrl',
                resolve: loader(['bar'])
            })
            .otherwise({
                redirectTo: document.location.pathname
            });
        }]);
    </script>
</body>
</html>

加载的foo.js:

//加载完成之后,注册控制器,这样resolve执行完之后就可以执行控制器了
app.registerCtrl('FooCtrl', function($scope){
    $scope.greet = 'Test Page';
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions