动态加载控制器

时间:2015-05-04 15:49:47

标签: javascript angularjs

我正在尝试设置一个角度应用程序,它将根据路径动态加载控制器。我正在关注tutorial,但我无法让它发挥作用。我也对适合我的教程代码做了一些小修改,但我不认为它们是问题。

我已将几乎所有的代码流放在这里,所以如果你想跳过它,那么错误就在最后的片段中。

注意:我已经改进了代码片段。

index.html 基础文件(我删除了ng-app和ng-controller参数,因为我意识到我用RequireJS手动调用它们)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Little Buddha</title>
    <link type="text/css" rel="stylesheet" href="assets/libs/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>

    <div>
        <div ng-view></div>
    </div>

    <script type="text/javascript" src="assets/libs/requirejs/require.js" data-main="app/main.js"></script>
</body>
</html>

如您所见,我正在使用RequireJS动态加载所有脚本。这是 main.js 配置文件: (我也编辑了这个文件,将角度和ngRoute添加到shim配置中)

require.config({
    baseUrl: '',
    urlArgs: 'dev=' + new Date().getTime(),
    paths: {
        'angular' : '/assets/libs/angular/angular.min',
        'ngRoute' : '/assets/libs/angular-route/angular-route.min',
        'routeResolver' : '/app/routeResolver',
        'app' : '/app/app',
        'constants' : '/app/global/constants',
        'AuthService' : '/app/global/AuthService',
        'AppController' : '/app/global/AppController',
    },
    shim: {
        'angular' : {
            exports : 'angular',
        },
        'ngRoute' : {
            deps : ['angular'],
        },
    }
});

require(
    [
        'ngRoute',
        'app',
        'routeResolver',
        'constants',
        'AppController',
        'AuthService',
    ],
    function () {
        angular.bootstrap(document, ['littleBuddha']);
    }
);

routeResolver.js

'use strict';

define([], function () {

    var routeResolver = function () {

        this.$get = function () {
            return this;
        };

        this.route = function () {

            var resolve = function (baseName, path, secure) {
                if (!path) path = '';

                var routeDef = {};
                routeDef.templateUrl = path + baseName + '.html';
                routeDef.controller = baseName + 'Controller';
                routeDef.secure = (secure) ? secure : false;
                routeDef.resolve = {
                    load: ['$q', '$rootScope', function ($q, $rootScope) {
                        var dependencies = [path + baseName + 'Controller.js'];
                        return resolveDependencies($q, $rootScope, dependencies);
                    }]
                };

                return routeDef;
            },

            resolveDependencies = function ($q, $rootScope, dependencies) {
                var defer = $q.defer();
                require(dependencies, function () {
                    defer.resolve();
                    $rootScope.$apply()
                });

                return defer.promise;
            };

            return {
                resolve: resolve
            }
        };

    };

    var servicesApp = angular.module('routeResolverServices', []);

    //Must be a provider since it will be injected into module.config()    
    servicesApp.provider('routeResolver', routeResolver);
});

app.js

'use strict';

define(['routeResolver'], function () {

    var app = angular.module('littleBuddha', ['routeResolverServices']);

    app.config(['$routeProvider', 'routeResolverProvider', '$controllerProvider', 
                '$compileProvider', '$filterProvider', '$provide',
        function ($routeProvider, routeResolverProvider, $controllerProvider, 
                  $compileProvider, $filterProvider, $provide) {

            console.log('test');

            app.register =
            {
                controller: $controllerProvider.register,
                directive: $compileProvider.directive,
                filter: $filterProvider.register,
                factory: $provide.factory,
                service: $provide.service
            };

            var route = routeResolverProvider.route;

            $routeProvider
                .when('/login', route.resolve('Login', '/app/components/login/'))
                .otherwise({ redirectTo: '/login' });

        }
    ]);

    return app;
});

最后, AppController.js

'use strict';

define(['app'], function (app) {

    //This controller retrieves data from the customersService and associates it with the $scope
    //The $scope is ultimately bound to the customers view due to convention followed by the routeResolver

    app.register.controller('AppController', function ($scope, USER_ROLES, AuthService) {

        $scope.currentUser = null;
        $scope.userRoles = USER_ROLES;
        $scope.isAuthorized = AuthService.isAuthorized;

        $scope.setCurrentUser = function (user) {
            $scope.currentUser = user;
        };

    });

    return app;

});

修改

所以,现在我找到了问题所在。在 app.js 中,永远不会调用app.config函数,因此永远不会应用寄存器参数,也不会计算路由。实际上,console.log('test')从未打印过。

1 个答案:

答案 0 :(得分:0)

我认为是因为你没有在routeResolver中初始化路线。

请注意,在本教程中,他们使用routeConfig立即运行routeResolver。我无法看到你初始化this.route函数的位置。

从教程:

    this.route = function (routeConfig) {

        var resolve = function (baseName, path, secure) {
                if (!path) path = '';

                var routeDef = {};
                routeDef.templateUrl = routeConfig.getViewsDirectory() + path + baseName + '.html';
                routeDef.controller = baseName + 'Controller';
                routeDef.secure = (secure) ? secure : false;
                routeDef.resolve = {
                    load: ['$q', '$rootScope', function ($q, $rootScope) {
                        var dependencies = [routeConfig.getControllersDirectory() + path + baseName + 'Controller.js'];
                        return resolveDependencies($q, $rootScope, dependencies);
                    }]
                };

                return routeDef;
            },

            resolveDependencies = function ($q, $rootScope, dependencies) {
                var defer = $q.defer();
                require(dependencies, function () {
                    defer.resolve();
                    $rootScope.$apply()
                });

                return defer.promise;
            };

        return {
            resolve: resolve
        }
    }(this.routeConfig);

此致:

    this.route = function (routeConfig) {

        var resolve = function (baseName, path, secure) {
            if (!path) path = '';

            var routeDef = {};
            routeDef.templateUrl = path + baseName + '.html';
            routeDef.controller = baseName + 'Controller';
            routeDef.secure = (secure) ? secure : false;
            routeDef.resolve = {
                load: ['$q', '$rootScope', function ($q, $rootScope) {
                    var dependencies = [path + baseName + 'Controller.js'];
                    return resolveDependencies($q, $rootScope, dependencies);
                }]
            };

            return routeDef;
        },

        resolveDependencies = function ($q, $rootScope, dependencies) {
            var defer = $q.defer();
            require(dependencies, function () {
                defer.resolve();
                $rootScope.$apply()
            });

            return defer.promise;
        };

        return {
            resolve: resolve
        }
    };

请注意,此功能未执行。

所以我认为您需要使用routeConfig对象运行此函数以使其定义并正常工作。

编辑:即使你不想要一个routeConfig对象(这似乎是你的目标),你仍然需要在没有传递参数的情况下运行该函数。

我最后的想法:

抱歉,我无法提供更多帮助。我会尝试另外两个建议,让我害怕。

你说app.config永远不会被调用。这可能与加载顺序有关。在main.js中试试这个。

require(
    [
        'ngRoute',
        'app',
        'routeResolver',
        'constants',
        'AppController',
        'AuthService',
    ],
    function () {
      angular.element(document).ready(function() {
          angular.bootstrap(document, ['littleBuddha']);
      });
    }
);

或者,它永远不会被调用,因为行

define(['routeResolver'], function () {

表示它首先尝试加载routeResolver。如果在routeResolver中有一些异常,那么它将无法按功能设置应用程序。在这种情况下,我建议通过调试来查看您在加载时通​​过routeResolver.js实际获得的距离。

我想出了这个想法,当我被这样的困难时,我通常首先让一个版本完全像演示一样,然后一步一步地向后工作看它何时停止工作。

祝你好运,对不起,我无法提供更多帮助。