2014-01-21 183 views
3

我在一个应用程序中使用ui-router将有几十个模板。每个模板都有一个控制器。使用AngularUI路由器动态加载控制器

从我一直在读,这样的事情(设置路由)应该工作的内容:

.config(function($stateProvider, $urlRouterProvider) { 
    $stateProvider 
    .state('start', { 
     url: '/start', 
     templateUrl: 'partials/start.html', 
     controller: 'StartCtrl' 
    }) 
}); 

这是假设StartCtrl以前定义。该应用程序最终将拥有数十个控制器,并且不希望一次性下载所有这些控制器的开销。如何仅在需要模板时加载控制器?

回答

4

我为此使用RequireJS。并且在供应商,说lazyProvider:

在你懒的提供商...

this.resolve = function(controller){ 
    return { myCtrl: ['$q',function ($q){ 
      var defer = $q.defer(); 
      require(['/app/controllers/'+controller,'myApp'],function(ctrl,myApp){ 
       myApp.register.controller(controller,ctrl); 
       defer.resolve(); 

      } 
      return defer.promise; 
     }] 
    }; 
}; 

在UI路由器resolve:财产做:

resolve: lazyProvider.resolve('myCtrl'); 

你需要公开提供商在你的应用程序寄存器,以便以后可以注册它们,如:

myApp.config(function($urlRouterProvider, $stateProvider, 
      $controllerProvider, $compileProvider, $filterProvider,$provide){ 
    //If your myApp isn't already a module... 
    define('myApp',[],function(){return myApp}); 
    myApp.register = { 
     controller: $controllerProvider.register, 
     directive: $compileProvider.directive, 
     filter: $filterProvider.register, 
     factory: $provide.factory, 
     service: $provide.service, 
     constant: $provide.constant 
    } 

而且你的控制器:

define(['/dependencies'],function(deps){ 
    function MyCtrl($scope){...} 
    return MyCtrl; 
} 

这基本上是什么丹Wahlin共用here

+0

有没有机会获得GitHub示例?在这一段时间里,遇到了各种各样的问题。 – mbursill

+0

嘿,对不起,我没有时间。基本上,我实现它类似于答案中链接的博客文章。你有什么特别的问题? – calebboyd

+0

这让我的大脑受伤,任何人都有一个真实世界的例子? – bryan

1

与@calebboyd样品玩弄后,我得到了它使用System.js和ES6工作。我喜欢这个实现是使用ES6模块,一切只依赖于已经唯一的文件名,所以你不需要关心控制器名称冲突,甚至不需要命名它们。控制器是匿名的。

此实现假定你有一个文件夹“页面”像这样的模板/控制器对:

 
/pages 
    /page1.html 
    /page1.js 
    /page2.html 
    /page2.js 

一旦你访问/#pages/page1,将同时加载模板和动态控制器。

这是你的 “app.js”:

import angular from 'angular'; 
import 'angular-ui-router'; 

angular.module('app', ['ui.router']) 
    .config(($stateProvider, $urlRouterProvider, $controllerProvider) => { 

    // save reference to the register method, so we can use inside the 'resolve' 
    var registerController = $controllerProvider.register; 

    // register a single state that takes the page name as a parameter 
    $stateProvider 
     .state('pages', { 
     url: "/pages/:name", 

     // the url and the controller name are dynamically created 
     templateUrl: $stateParams => "pages/" + $stateParams.name + ".html", 
     controllerProvider: $stateParams => $stateParams.name + '_DynamicController as vm', 

     resolve: { 

      'ctrl': ($stateParams, $q) => { 

      var script = 'pages/' + $stateParams.name; 
      var controllerName = $stateParams.name + '_DynamicController'; 

      // once System.js loads the module, we register using the 
      // saved registerController function with the dynamic name 
      return System.import(script) 
       .then(ctrl => registerController(controllerName, ctrl['default'])); 
      } 
     } 
     }); 
    }); 

这里是 “page1.js” 样本控制器:在 “page1.html”

export default class { 
    constructor() { 
    this.data = "inside the controller"; 
    } 
} 

样本模板:

<h1>Page1 Template</h1> 
Loaded: {{ vm.data }}