AngularJS + ui-router + RequireJS异步加载注册controller/directive/filter/service
一般情况下我们会将项目所用到的controller/directive/filter/sercive预先加载完再初始化AngularJS模块,但是当项目比较复杂的情况下,应该是打开对应的界面才加载对应的controller等资源,但是AngularJS一旦初始化,之后加载的controller/directive/filter/sercive是不会自动注册到模块上的。用AngularJS + ui-router + RequireJS来构建项目应该是比较常见的,所以我就基于这个条件来看看如何解决这个问题。
目录结构:
HTML结构非常简单,两个链接,分别改变路由切换到不同子页面:
<html> <head> <title>AngularJS + ui-router + RequireJS异步加载注册controller</title> </head> <body> <a href="#home">home</a> <a href="#local">local</a> <div ui-view></div> <script type="text/javascript" src="js/require.js" data-main="js/main"></script> </body> </html>
main.js配置文件路径,初始化模块
require.config({ baseUrl: 'js', paths: { 'app': 'app', 'angular': 'angular.min', 'router': 'angular-ui-router' }, shim: { 'router': { deps: ['angular'] } } }) // 手动初始化myModule模块 require(['app'],function(){ angular.bootstrap(document, ['myModule']) })
app.js配置路由并返回myModule模块
define(['router'],function(){ var app = angular.module("myModule", ['ui.router']) .config(function($stateProvider, $urlRouterProvider){ $urlRouterProvider.otherwise('home'); $stateProvider .state("home",{ url:"/home", template: '<p>这里是home页面</p>' }) .state("local",{ url:"/local", template: '<p>这里是local页面</p>' }) }) return app; })
界面如下,现在可以点击home和local切换到对应的子页面
接下来要做的是,切换到home界面要加载homeCtrl控制器,切换到local页面加载localCtrl控制器,我们将会用到$controllerProvider来手动注册控制器。怎么拿到$controllerProvider到引用呢?
对angular应用来说,模块对象是全局的,正好可以用来保存$controllerProvider的引用
在app.js文件define内部加上以下代码
app.config(function($controllerProvider,$compileProvider,$filterProvider,$provide){ app.register = { //得到$controllerProvider的引用 controller : $controllerProvider.register, //同样的,这里也可以保存directive/filter/service的引用 directive: $compileProvider.directive, filter: $compileProvider.register, service: $provide.service }; })
接着在路由中配置要加载的控制器/指令/过滤器/服务
.config(['$stateProvider','$urlRouterProvider',function($stateProvider, $urlRouterProvider){ $urlRouterProvider.otherwise('home'); $stateProvider .state("home",{ url:"/home", controller: 'homeCtrl', template: '<p>{{str}}</p>', resolve: { loadCtrl: ["$q", function($q) { var deferred = $q.defer(); //异步加载controller/directive/filter/service require([ 'controller/homeCtrl' ], function() { deferred.resolve(); }); return deferred.promise; }] } }) .state("local",{ url:"/local", controller: 'localCtrl', template: '<p>{{str}}</p>', resolve: { loadCtrl: ["$q", function($q) { var deferred = $q.defer(); //异步加载controller/directive/filter/service require([ 'controller/localCtrl' ], function() { deferred.resolve(); }); return deferred.promise; }] } }) }])
最后是控制器的写法,为了省事就两个写在一块了
define(['app'],function(app){ app.register .controller('homeCtrl', function($scope){ $scope.str = 'home page'; }) app.register .controller('localCtrl',function($scope){ $scope.str = 'local page' }) })
刷新页面, 就可以动态加载controller了。
directive/filter/service的写法类似于controller,不再赘述,自己动手丰衣足食。 实例放在git上
By:古德God于 2016/01/15 00:30:47
原文链接:http://www.cnblogs.com/wangmeijian/p/5020788.html