【问题标题】:Load controller dynamically based on route group基于路由组动态加载控制器
【发布时间】:2017-10-19 15:42:05
【问题描述】:

是否可以根据路由组动态加载控制器、js 文件和模板?无效的伪代码:

$routeProvider.when('/:plugin', function(plugin) {
  templateUrl: 'plugins/' + plugin + '/index.html',
  controller: plugin + 'Ctrl',
  resolve: { /* Load the JS file, from 'plugins/' + plugin + '/controller.js' */ }
});

我见过很多这样的问题,但没有一个基于路由组加载 js 文件/控制器。

【问题讨论】:

    标签: angularjs angularjs-controller angular-routing


    【解决方案1】:

    在@calebboyd、http://ify.io/lazy-loading-in-angularjs/http://weblogs.asp.net/dwahlin/archive/2013/05/22/dynamically-loading-controllers-and-views-with-angularjs-and-requirejs.aspx 的启发下,我设法解决了这个问题

    使用http://dustindiaz.com/scriptjs

    app.js

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

    然后我注册“按组加载控制器”路由。

    $routeProvider.when('/:plugin', {
    
      templateUrl: function(rd) {
        return 'plugin/' + rd.plugin + '/index.html';
      },
    
      resolve: {
        load: function($q, $route, $rootScope) {
    
          var deferred = $q.defer();
    
          var dependencies = [
            'plugin/' + $route.current.params.plugin + '/controller.js'
          ];
    
          $script(dependencies, function () {
            $rootScope.$apply(function() {
              deferred.resolve();
            });
          });
    
          return deferred.promise;
        }
      }
    });
    

    controller.js

    app.register.controller('MyPluginCtrl', function ($scope) {
      ...
    });
    

    index.html

    <div ng-controller="MyPluginCtrl">
      ...
    </div>
    

    【讨论】:

    • 这给了我一个“$script is not defined”的错误。虽然我也在使用 requirejs。
    • 我迟到了 2 年多,但是四处寻找我仍然找不到更好的解决方案,而且我仍然无法相信 Angular 团队中没有人考虑解决这在 Angular 中,而不必求助于 script.js 和 require.js 之类的 3rd-party 库。我错过了什么吗?他们可能在 Angular 2 中解决了这个问题吗?
    【解决方案2】:

    您可以使用 RequireJS 来执行此操作。比如:

    $routeProvider.when('/:plugin',{
        templateUrl: 'plugins/' + plugin + '/index.html',
        controller: plugin + 'Ctrl',
        resolve: {myCtrl: function($q){
            var deferred = $q.defer();
            require('myCtrlFile',function(){
                deferred.resolve();
            });
            return deferred.promise;
        }}
    });
    

    您还需要动态注册控制器。通过在应用配置中公开您的提供程序。

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

    您的控制器文件可能如下所示:

    define(['app'],function(app){
        app.register.controller('myCtrl',MyCtrlFunction);
    });
    

    这只是一般的想法。我使用与here 描述的实现类似的实现@

    我也使用 ui-router。我不确定 ngRoute 的行为是否相同。

    【讨论】:

    • 因为 when() 不将函数作为第二个参数,所以我无法访问控制器属性或解析属性中的“插件”。
    【解决方案3】:

    以下是您可以为此代码执行的一些解决方案

    $routeProvider.when('/:plugin', function(plugin) {
      templateUrl: 'plugins/' + plugin + '/index.html',
      controller: fun,
      loadFrom:"assets/controller/myJsController"// this is our custom parameter we are passing to controller to identify the remote controller file.
    });
    

    我们将为所有控制器创建一个父函数,并根据路由配置中的定义(在路由配置的 loadFrom 键中)调用此函数内的所有控制器。

     function fun($scope, $http, $location, $timeout, $route) {
            $timeout(function () {
            var path = $route.current.loadForm;
            $http.get("${pageContext.servletContext.contextPath}/resource/controller/" + path + ".js")
                    .then(function (rsp) {
                    eval(rsp.data);
                    });
            });
            };
    

    assets/controller/myJsController.js 文件中,代码将如下所示

    (function($scope){
    //the whole code for controller will be here.
       $scope.message="working."
    
    
     })($scope)
    

    唯一需要记住的是,在父函数中必须使用所有依赖项。

    【讨论】:

      【解决方案4】:

      用更少的代码激活 this 的最简单方法

      require.js 配置文件。

      require.config({
          urlArgs: 'v=1.0',
          baseUrl: '/'
      });

      app.config(['$controllerProvider', '$compileProvider', '$filterProvider', '$provide','$routeProvider',function($controllerProvider, $compileProvider, $filterProvider, $provide,$routeProvider) {
        app.register = {
          controller: $controllerProvider.register,
          directive: $compileProvider.directive,
          filter: $filterProvider.register,
          factory: $provide.factory,
          service: $provide.service
        };
        // Resolver to load controller, service, directive
        var resolveController = function(dependencies) {
            return {
              load: ['$q', '$rootScope', function ($q, $rootScope) {
                var defer = $q.defer();
                require(dependencies, function () {
                    defer.resolve();
                    $rootScope.$apply();
                });
                return defer.promise;
              }]
            }
        };
        $routeProvider
          .when("/home", {
              templateUrl : "templates/home.html",
              controller: 'HomeCtrl',
              resolve: resolveController(['controller/HomeCtrl'])
          })
          .when("/ContactUs", {
              templateUrl : "templates/ContactUs.html",
              controller: 'ContactUsCtrl',
              resolve: resolveController(['controller/ContactUsCtrl'])
          })
          .when("/About", {
              templateUrl : "templates/About.html",
              controller: 'AboutCtrl',
              resolve: resolveController(['controller/AboutCtrl'])
          });
        $routeProvider.otherwise('/home');
      }]);

      您的控制器应如下所示。

      define(['app'],function(app){
          app.register.controller('HomeCtrl',['$scope',function($scope){
            // Controller code goes here
          }]);
      });

      【讨论】:

        猜你喜欢
        • 2018-07-17
        • 1970-01-01
        • 1970-01-01
        • 2012-06-10
        • 1970-01-01
        • 2014-07-02
        • 1970-01-01
        • 2014-11-07
        • 2017-10-17
        相关资源
        最近更新 更多