【问题标题】:Load controllers dynamically动态加载控制器
【发布时间】:2015-05-04 15:49:47
【问题描述】:

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

我已经把我几乎所有的代码流都放在这里了,所以如果你想跳过它,错误在最后一个sn-ps中。

注意:我已经更改了代码 sn-ps。

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 动态加载所有脚本。这是 ma​​in.js 配置文件: (我还编辑了这个文件,将 angular 和 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') 从未被打印出来。

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    我认为是因为您没有在 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 对象(这似乎是您的目标),您仍然需要在不传递参数的情况下运行该函数。

    我最后的想法:

    抱歉,我无法提供更多帮助。我会再尝试 2 条建议,恐怕我就是这样。

    你说 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 的程度。

    那是我的想法,当我被这样卡住时,我通常会先让一个版本像演示一样完全工作,然后逐步回到我真正想要看到的版本当它停止工作时。

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

    【讨论】:

    • 实际上在教程中,他们使用该命令调用 routeConfig 函数并设置内部路径。 this.route 之后在 app.js 文件中使用命令 var route = routeResolverProvider.route;$routeProvider.when('/login', route.resolve('Login', '/app/components/login/')) 调用。无论如何,我尝试了您的解决方案,但没有任何改变。
    • 在我看来,this.route 在声明时应该立即初始化,现在函数也不需要使用 routeConfig。将您问题中的代码更新为您现在使用的代码,并考虑制作一个 plunkr 进行演示和编辑。
    • 我更新了我的问题。然而,作为一个 php 开发人员,这对我来说是全新的,而且变得相当复杂。即使我让它工作,我想我也不会完全理解为什么。我想我会用 ocLazyLoad 再试一次,看起来更直观。 oclazyload.readme.io/v1.0
    • 我一次又一次地更新,直到发现问题。现在我知道它在哪里,但我不知道如何解决它......
    猜你喜欢
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多