├── README.md └── angularJs-uiRouter-RequireJsDemo ├── .idea ├── .name ├── eLinkDashboard1.0.iml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── app ├── business │ ├── home │ │ ├── config │ │ │ └── routerconfig.js │ │ ├── controllers │ │ │ ├── homeCtrl.js │ │ │ ├── httpTestCtrl.js │ │ │ ├── localCtrl.js │ │ │ ├── preViewCtrl.js │ │ │ ├── routertestCtrl.js │ │ │ ├── showDataCtrl.js │ │ │ └── testCtrl.js │ │ ├── partials │ │ │ ├── home.html │ │ │ ├── httpTest.html │ │ │ ├── local.html │ │ │ ├── preView.html │ │ │ ├── routertest.html │ │ │ ├── showData.html │ │ │ └── test.html │ │ └── services │ │ │ └── booksService.js │ └── services │ │ └── httpServices.js └── config │ ├── app.js │ ├── appregister.js │ ├── main.js │ ├── routerconfig.js │ └── routermodel.js ├── index.html ├── lib ├── angular-ui-router.js ├── angular.js ├── angular.min.js ├── angular.min2.js ├── bootstrap.js ├── domReady.js ├── jquery.media.js ├── jquery.min.js └── require.js └── them └── css └── bootstrap.css /README.md: -------------------------------------------------------------------------------- 1 | 作者:花剌子模 2 | 链接:https://www.zhihu.com/question/33251004/answer/116589753 3 | 来源:知乎 4 | 著作权归作者所有,转载请联系作者获得授权。 5 | 6 | 这个问题我遇到过 我来说说我的解决方案 7 | 首先我的项目采用angularJS +requireJS + ui-router 8 | 实现了 动态按需求加载html 和controller 以及动态配置路由 9 | 本人文笔有限 直接说我是怎样实现的。 10 | 11 | 首先在 mian.js中初始化模块 12 | 13 | ``` 14 | require(["domReady!",'app'],function( document){ 15 | angular.bootstrap(document, ['myModule']) 16 | }) 17 | ``` 18 | 19 | 20 | 初始化模块以后 需要重新注册各项服务 关于为何要这样 可以详细看答案 各位大神已经详细说明了 21 | AngularJS按需动态加载template和controller? 22 | AngularJS按需动态加载template和controller? - 前端开发框架和库 23 | 24 | ``` 25 | var app = angular.module("myModule", ['ui.router']); 26 | app.config(function($controllerProvider,$compileProvider,$filterProvider,$provide,$stateProvider){ 27 | app.register = { 28 | //得到$controllerProvider的引用 29 | controller : $controllerProvider.register, 30 | //同样的,这里也可以保存directive/filter/service的引用 31 | directive: $compileProvider.directive, 32 | filter: $filterProvider.register, 33 | service: $provide.service, 34 | factory:$provide.factory, 35 | stateProvider:$stateProvider 36 | }; 37 | 38 | ``` 39 | 40 | 41 | 这个文件返回 app 对象, 在另外一个文件中单独返回app.register , 这样 其他需要使用这些服务的 就不用写 app.register.controller("balabala 反正我是这样写的 。 42 | 43 | ``` 44 | 45 | define(["app"],function(app){ 46 | return app.register; 47 | }) 48 | 49 | ``` 50 | 51 | 52 | 在另一个文件中写了一个公共方法 作为ui-router 配置的公共调用方法 53 | 代码如下 54 | 55 | 这里return 了一个routerState 方法 ,外部可以调用这个方法对其传参 这个方法可以实现自动配置路由 56 | 关键是调用这个方法 这个是在register 里面配置了的app.stateProvider.state() 57 | 58 | ``` 59 | define(["config/appregister"],function(app) { 60 | return { 61 | routerState:function(state,url,ctrl,params) { 62 | if(!angular.isString(state)||!angular.isString(url) || !angular.isString(ctrl)){ 63 | return 64 | } 65 | var strurl = ctrl; 66 | var ctrlName = strurl.substring(strurl.lastIndexOf('/')+1); 67 | //todo 字符串匹配校验待做 68 | app.stateProvider.state(state,{ 69 | url:"/"+ state, 70 | controller: ctrlName, 71 | templateUrl: url, 72 | resolve: { 73 | loadCtrl: ["$q", function($q) { 74 | var deferred = $q.defer(); 75 | //异步加载controller/directive/filter/service 76 | require([ 77 | ctrl 78 | ], function() { deferred.resolve(); }); 79 | return deferred.promise; 80 | }] 81 | } 82 | }) 83 | } 84 | } 85 | }) 86 | 87 | ``` 88 | 这样 写好了公共文件 。现在加入我的业务分成几个模块 89 | 我要实现 当用户 点击具体模块的时候再 加载器对应的模块下的路由配置 90 | 91 | 92 | 看到这里其实就讲完了 下面的唠叨可以不看了 93 | 94 | 下面在业务模块中写了个方法具体来调用上面的方法 实现路由配置 95 | 我做的demo 目录大概是这样的 96 | 下面这个文件是我一个业务的模块的主文件, 在加载这个主文件的时候 , 先调用上面的方法生成该业务下的路由 。 97 | 98 | 代码如下: 99 | 先调用上面的routerState 方法 对其传参 ,执行完以后就配置好了 。 100 | 101 | ``` 102 | 103 | define(['config/routerconfig'],function(router){ 104 | router.routerState("routertest","app/business/home/partials/routertest.html","business/home/controllers/routertestCtrl"); 105 | }) 106 | 107 | 108 | ``` 109 | 110 | 在配置好了以后 点击上面配置的路由 可以跳转到刚配好的路由上去 111 | 112 | ``` 113 | define(["business/home/config/routerconfig",'config/appregister'],function(routercongfig,app){ 114 | app 115 | .controller('localCtrl',function($scope,$state){ 116 | $scope.str = '作为主文件同时配置home 业务模块下的细分模块'; 117 | $scope.state = function(){ 118 | $state.go("routertest"); 119 | } 120 | 121 | }) 122 | 123 | }) 124 | 125 | ``` 126 | 127 | 128 | 先写到这儿 ,现在项目才立项 ,刚好昨天实现了这个 后面有优化方案 再来填坑吧 129 | ------------------------------------2016/8/13 130 | 131 | 132 | 133 | 补充一点 , 1 之前有朋友下载了我的demo 打包出现问题 解释一下 ,因为angularJS控制器里面是注入服务多数情况下不是严格的 ["$scope",function($scope){}] 按照这种方式来写的 ,二是直接写成 app.controller(function($scope,$q,balabala){}) , 这种推断注入在项目运行时框架内可以识别 但是打包后 都变成 a ,b , c 了 所以最后会报注入错误, 项目打包的时候需要先用ngAnnotate 处理一下注入问题, 我是用的 gulp 工具做的处理 方法如下 134 | 135 | ``` 136 | 137 | var gulp = require('gulp'); 138 | var ngAnnotate = require('gulp-ng-annotate'); 139 | gulp.task('default', function () { 140 | return gulp.src('dashboard/app/**/*.js') 141 | .pipe(ngAnnotate()) 142 | .pipe(gulp.dest('dist'));}) 143 | ``` 144 | 145 | 通过这个任务流处理以后 就可以将原来推断注入全部转换成显式注入 然后呢 ,就可以愉快的打包了 。2 ,项目后期可以做通过控制路由来配置角色权限 以及其他操作 146 | 147 | ``` 148 | 149 | $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) { 150 | $rootScope.routerToStateName = toState.name; 151 | if(toState.name =="login"){ 152 | auth.setFormState(fromState.name); 153 | } 154 | if(fromState.name.indexOf("search")>-1&&toState.name.indexOf("search")<0){ 155 | $rootScope.GLOBALKEYWORD = "" 156 | } 157 | //鉴别当前角色是否具有路由访问权限 158 | if( !auth.isAccessUrl(toState.name)){ 159 | $state.go("indexCtrl"); 160 | event.preventDefault(); 161 | } 162 | 163 | ``` 164 | 165 | 我把代码贴到我的github上面去了 欢迎交流GitHub - yangfan0095/angularJs-uiRouter-RequireJsDemo: angularJs-uiRouter-RequireJs demo 实现模块按需求加载 路由配置 按需求加载 欢迎交流。 166 | 167 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/.idea/.name: -------------------------------------------------------------------------------- 1 | eLinkDashboard1.0 -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/.idea/eLinkDashboard1.0.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 133 | 134 | 135 | 145 | 146 | 147 | 148 | true 149 | 150 | 151 | 152 | 153 | 154 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 191 | 192 | 193 | 194 | 197 | 198 | 201 | 202 | 203 | 204 | 207 | 208 | 211 | 212 | 215 | 216 | 217 | 218 | 221 | 222 | 225 | 226 | 229 | 230 | 233 | 234 | 235 | 236 | 239 | 240 | 243 | 244 | 247 | 248 | 251 | 252 | 253 | 254 | 257 | 258 | 261 | 262 | 265 | 266 | 269 | 270 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 1470909136073 323 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/config/routerconfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Administrator on 2016/8/12. 3 | */ 4 | define(['config/routerconfig'],function(router){ 5 | router.routerState("routertest","app/business/home/partials/routertest.html","business/home/controllers/routertestCtrl"); 6 | }) -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/controllers/homeCtrl.js: -------------------------------------------------------------------------------- 1 | define(['config/appregister',"business/home/services/booksService","business/services/httpServices"],function(app,booksService){ 2 | app.controller('homeCtrl', function($scope,$state,booksService){ 3 | $scope.str = 'home page'; 4 | $scope.sex = 0; 5 | $scope.state = { 6 | "local":"local", 7 | "test":"test", 8 | "home":"home", 9 | "preView":"preView", 10 | "httpTest":"httpTest", 11 | "showData":{ 12 | state:"showData", 13 | toParams:{city:"shanghai",parts:"pudong",id:3456,username:"jackMa"} 14 | } 15 | } 16 | $scope.routerChange = function(state){ 17 | if(angular.isObject(state.toParams)){ 18 | $state.go(state.state,state.toParams); 19 | }else{ 20 | $state.go(state); 21 | } 22 | } 23 | $scope.books = booksService.books; 24 | console.log($scope.books) 25 | }) 26 | 27 | app.filter('sexFilter', function(){ 28 | return function(sex){ 29 | return ['男','女'][sex]; 30 | } 31 | }) 32 | app.directive('myDirective', function(){ 33 | return { 34 | restrict: "E", 35 | replace: true, 36 | template: "
指令测试
" 37 | } 38 | }) 39 | }) -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/controllers/httpTestCtrl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Administrator on 2016/8/12. 3 | */ 4 | define(['config/appregister'],function(app){ 5 | app. controller("httpTestCtrl",function($scope,$http,$state,getProducts ){ 6 | $scope.displayMode = "list"; 7 | $scope.currentProduct = null; 8 | $scope.constant = { 9 | create :"create", 10 | preview:"preView" 11 | } 12 | //todo 13 | $scope.listProducts = function(){ 14 | var requestion ={ 15 | type:"GET", 16 | url:"products" 17 | } 18 | getProducts.getData(requestion).success(function(data){ 19 | $scope.products = data; 20 | }); 21 | } 22 | $scope.deleteProduct = function(product){ 23 | $http({ 24 | method:"DELETE", 25 | url:baseUrl+product.id 26 | }).success(function(){ 27 | $scope.products.splice($scope.products.indexOf(product),1); 28 | }) 29 | } 30 | $scope.createProduct = function(product){ 31 | // $scope.products.push(product); 32 | $http.post(baseUrl,product).success(function(newProduct){ 33 | $scope.products.push(newProduct); 34 | }) 35 | } 36 | $scope.updateProduct = function(product){ 37 | $http({ 38 | url:baseUrl + product.id, 39 | method:"PUT", 40 | data:product 41 | }).success(function(modifiedProduct){ 42 | for(var i = 0 ; i<$scope.products.length;i++){ 43 | if($scope.products[i].id == modifiedProduct.id){ 44 | $scope.products[i] = modifiedProduct; 45 | break; 46 | } 47 | } 48 | }) 49 | } 50 | $scope.editOrCreateProduct = function(product){ 51 | $scope.currentProduct = product?angular.copy(product):{}; 52 | $scope.displayMode = "edit"; 53 | } 54 | $scope.saveEdit = function(product){ 55 | if(angular.isDefined(product.id)){ 56 | $scope.updateProduct(product); 57 | }else{ 58 | $scope.createProduct(product); 59 | } 60 | } 61 | $scope.canelEdit = function(){ 62 | $scope.currentProduct = {}; 63 | $scope.displayMode = "list"; 64 | } 65 | $scope.listProducts(); 66 | $scope.location = function(path){ 67 | //var path = "create"; 68 | $state.go(path); 69 | } 70 | 71 | }) 72 | }) -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/controllers/localCtrl.js: -------------------------------------------------------------------------------- 1 | define(["business/home/config/routerconfig",'config/appregister'],function(routercongfig,app){ 2 | app 3 | .controller('localCtrl',function($scope,$state){ 4 | $scope.str = '作为主文件同时配置home 业务模块下的细分模块'; 5 | $scope.state = function(){ 6 | $state.go("routertest"); 7 | } 8 | 9 | }) 10 | 11 | }) -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/controllers/preViewCtrl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Administrator on 2016/8/12. 3 | */ 4 | define(['config/appregister',"jquery","domReady","jqueryMedia"],function(app,$,doc){ 5 | app 6 | .controller('preViewCtrl',function($scope){ 7 | $scope.str = 'preView page'; 8 | $scope.pdfPath = "resources/pdf/webguifan.pdf"; 9 | var screenWidth = screen.width; 10 | var screenHeight = screen.height; 11 | var preView = { 12 | width:screenWidth-80, 13 | height:screenHeight-20 14 | } 15 | //考虑到移动端情况 暂时设置为200px 16 | if(screenWidth>200){ 17 | //... 18 | } 19 | doc(function(){ 20 | $('.media').media({width: preView.width, height: preView.height}); 21 | $('.pdfContainer' ).css({width: preView.width, height: preView.height,margin:"0 auto"}); 22 | }) 23 | }) 24 | }) -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/controllers/routertestCtrl.js: -------------------------------------------------------------------------------- 1 | define(['config/appregister','business/home/config/routerconfig'],function(app){ 2 | app.controller('routertestCtrl',function($scope){ 3 | $scope.str = 'router test'; 4 | }) 5 | }) -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/controllers/showDataCtrl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Administrator on 2016/8/12. 3 | */ 4 | define(['config/appregister',"business/services/httpServices"],function(app){ 5 | app.controller("showDataCtrl",function($scope,$stateParams,$http,getProducts){ 6 | $scope.params = $stateParams; 7 | console.log($scope.params); 8 | var requestion ={ 9 | type:"GET", 10 | url:"products" 11 | } 12 | getProducts.getData(requestion).success(function(data){ 13 | console.log(data); 14 | }).error(function(){ 15 | console.log("bad Requestion") 16 | }) 17 | }) 18 | }) 19 | 20 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/controllers/testCtrl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Administrator on 2016/8/11. 3 | */ 4 | define(["require",'config/appregister',"jquery","domReady"],function(require,app){ 5 | app.controller('testCtrl',function($scope){ 6 | $scope.name = 'angularJS 异步按需求加载 controller 和view'; 7 | 8 | var doc = document.getElementById("123"); 9 | require(['domReady!'], function (doc) { 10 | $("#123").css({"background":"#666"}); 11 | }); 12 | }) 13 | }) 14 | 15 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/partials/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |

{{str}}


14 | 过滤器应用:{{sex | sexFilter}}

15 | Service应用: {{book.id + 1}} :{{book.name}}

' 16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/partials/httpTest.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 |
NameCategory Price
{{item.name}}{{item.category}}{{item.price | currency}} 17 | 18 | 19 |
23 |
24 | 25 | New 26 | previewPdf 27 |
28 |
-------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/partials/local.html: -------------------------------------------------------------------------------- 1 |

local

2 |
3 | 4 |
-------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/partials/preView.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/partials/routertest.html: -------------------------------------------------------------------------------- 1 |

{{str}}

-------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/partials/showData.html: -------------------------------------------------------------------------------- 1 |
2 |

获取当前页面路由参数

3 |

params.city :{{params.city}}

4 |

params.parts:{{params.parts}}

5 |

params.id:{{params.id}}

6 |

params.username:{{params.username}}

7 |
-------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/partials/test.html: -------------------------------------------------------------------------------- 1 |
2 |

test

3 |

{{name}}

4 |
5 |
6 |
7 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/home/services/booksService.js: -------------------------------------------------------------------------------- 1 | define(['app'],function(app){ 2 | //Service比较特殊,加载后还需要手动注入控制器 3 | app.register.service('booksService', function(){ 4 | this.books = [ 5 | { 6 | id: 0, 7 | name: 'book1' 8 | }, 9 | { 10 | id: 1, 11 | name: 'book2' 12 | } 13 | ]; 14 | return this; 15 | }) 16 | }) -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/business/services/httpServices.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Administrator on 2016/8/12. 3 | */ 4 | define(['config/appregister'],function(app){ 5 | app.factory("getProducts",function($http){ 6 | var baseUrl = "http://localhost:2403"; 7 | return { 8 | getData : function(requestion) { 9 | return $http({ 10 | method: requestion.type, 11 | url:baseUrl+"/"+ requestion.url 12 | }) 13 | } 14 | } 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/app/config/app.js: -------------------------------------------------------------------------------- 1 | define(["config/routermodel", 'angular', 'router'], function (routermodel) { 2 | var app = angular.module("myModule", ['ui.router']); 3 | app.config(function ($controllerProvider, $compileProvider, $filterProvider, $provide, $stateProvider) { 4 | app.register = { 5 | //得到$controllerProvider的引用 6 | controller: $controllerProvider.register, 7 | //同样的,这里也可以保存directive/filter/service的引用 8 | directive: $compileProvider.directive, 9 | filter: $filterProvider.register, 10 | service: $provide.service, 11 | factory: $provide.factory, 12 | stateProvider: $stateProvider 13 | }; 14 | }).config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) { 15 | $urlRouterProvider.otherwise('home'); 16 | var model = routermodel; 17 | var index = 0; 18 | function routerSet(){ 19 | //循环调用 实现将model中所有设置好的对象 通过 $stateProvide.state()一一配置 20 | var item = model[index]; 21 | if (!angular.isString(item.state) || !angular.isString(item.url) || !angular.isString(item.url)) { 22 | return 23 | } 24 | var strurl = item.ctrl; 25 | var ctrlName = strurl.substring(strurl.lastIndexOf('/')+1); 26 | //todo 类型判断别待完善 27 | $stateProvider.state(item.state, { 28 | url:"/"+ item.state, 29 | controller: ctrlName, 30 | templateUrl: item.url, 31 | resolve: { 32 | loadCtrl: ["$q", function($q) { 33 | var deferred = $q.defer(); 34 | //异步加载controller/directive/filter/service 35 | require([ 36 | item.ctrl 37 | ], function() { deferred.resolve(); }); 38 | return deferred.promise; 39 | }] 40 | } 41 | }) 42 | index++; 43 | if(index 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /angularJs-uiRouter-RequireJsDemo/lib/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* =================================================== 2 | * bootstrap-transition.js v2.3.2 3 | * http://getbootstrap.com/2.3.2/javascript.html#transitions 4 | * =================================================== 5 | * Copyright 2013 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) 27 | * ======================================================= */ 28 | 29 | $(function () { 30 | 31 | $.support.transition = (function () { 32 | 33 | var transitionEnd = (function () { 34 | 35 | var el = document.createElement('bootstrap') 36 | , transEndEventNames = { 37 | 'WebkitTransition' : 'webkitTransitionEnd' 38 | , 'MozTransition' : 'transitionend' 39 | , 'OTransition' : 'oTransitionEnd otransitionend' 40 | , 'transition' : 'transitionend' 41 | } 42 | , name 43 | 44 | for (name in transEndEventNames){ 45 | if (el.style[name] !== undefined) { 46 | return transEndEventNames[name] 47 | } 48 | } 49 | 50 | }()) 51 | 52 | return transitionEnd && { 53 | end: transitionEnd 54 | } 55 | 56 | })() 57 | 58 | }) 59 | 60 | }(window.jQuery);/* ========================================================== 61 | * bootstrap-alert.js v2.3.2 62 | * http://getbootstrap.com/2.3.2/javascript.html#alerts 63 | * ========================================================== 64 | * Copyright 2013 Twitter, Inc. 65 | * 66 | * Licensed under the Apache License, Version 2.0 (the "License"); 67 | * you may not use this file except in compliance with the License. 68 | * You may obtain a copy of the License at 69 | * 70 | * http://www.apache.org/licenses/LICENSE-2.0 71 | * 72 | * Unless required by applicable law or agreed to in writing, software 73 | * distributed under the License is distributed on an "AS IS" BASIS, 74 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 75 | * See the License for the specific language governing permissions and 76 | * limitations under the License. 77 | * ========================================================== */ 78 | 79 | 80 | !function ($) { 81 | 82 | "use strict"; // jshint ;_; 83 | 84 | 85 | /* ALERT CLASS DEFINITION 86 | * ====================== */ 87 | 88 | var dismiss = '[data-dismiss="alert"]' 89 | , Alert = function (el) { 90 | $(el).on('click', dismiss, this.close) 91 | } 92 | 93 | Alert.prototype.close = function (e) { 94 | var $this = $(this) 95 | , selector = $this.attr('data-target') 96 | , $parent 97 | 98 | if (!selector) { 99 | selector = $this.attr('href') 100 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 101 | } 102 | 103 | $parent = $(selector) 104 | 105 | e && e.preventDefault() 106 | 107 | $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) 108 | 109 | $parent.trigger(e = $.Event('close')) 110 | 111 | if (e.isDefaultPrevented()) return 112 | 113 | $parent.removeClass('in') 114 | 115 | function removeElement() { 116 | $parent 117 | .trigger('closed') 118 | .remove() 119 | } 120 | 121 | $.support.transition && $parent.hasClass('fade') ? 122 | $parent.on($.support.transition.end, removeElement) : 123 | removeElement() 124 | } 125 | 126 | 127 | /* ALERT PLUGIN DEFINITION 128 | * ======================= */ 129 | 130 | var old = $.fn.alert 131 | 132 | $.fn.alert = function (option) { 133 | return this.each(function () { 134 | var $this = $(this) 135 | , data = $this.data('alert') 136 | if (!data) $this.data('alert', (data = new Alert(this))) 137 | if (typeof option == 'string') data[option].call($this) 138 | }) 139 | } 140 | 141 | $.fn.alert.Constructor = Alert 142 | 143 | 144 | /* ALERT NO CONFLICT 145 | * ================= */ 146 | 147 | $.fn.alert.noConflict = function () { 148 | $.fn.alert = old 149 | return this 150 | } 151 | 152 | 153 | /* ALERT DATA-API 154 | * ============== */ 155 | 156 | $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) 157 | 158 | }(window.jQuery);/* ============================================================ 159 | * bootstrap-button.js v2.3.2 160 | * http://getbootstrap.com/2.3.2/javascript.html#buttons 161 | * ============================================================ 162 | * Copyright 2013 Twitter, Inc. 163 | * 164 | * Licensed under the Apache License, Version 2.0 (the "License"); 165 | * you may not use this file except in compliance with the License. 166 | * You may obtain a copy of the License at 167 | * 168 | * http://www.apache.org/licenses/LICENSE-2.0 169 | * 170 | * Unless required by applicable law or agreed to in writing, software 171 | * distributed under the License is distributed on an "AS IS" BASIS, 172 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 173 | * See the License for the specific language governing permissions and 174 | * limitations under the License. 175 | * ============================================================ */ 176 | 177 | 178 | !function ($) { 179 | 180 | "use strict"; // jshint ;_; 181 | 182 | 183 | /* BUTTON PUBLIC CLASS DEFINITION 184 | * ============================== */ 185 | 186 | var Button = function (element, options) { 187 | this.$element = $(element) 188 | this.options = $.extend({}, $.fn.button.defaults, options) 189 | } 190 | 191 | Button.prototype.setState = function (state) { 192 | var d = 'disabled' 193 | , $el = this.$element 194 | , data = $el.data() 195 | , val = $el.is('input') ? 'val' : 'html' 196 | 197 | state = state + 'Text' 198 | data.resetText || $el.data('resetText', $el[val]()) 199 | 200 | $el[val](data[state] || this.options[state]) 201 | 202 | // push to event loop to allow forms to submit 203 | setTimeout(function () { 204 | state == 'loadingText' ? 205 | $el.addClass(d).attr(d, d) : 206 | $el.removeClass(d).removeAttr(d) 207 | }, 0) 208 | } 209 | 210 | Button.prototype.toggle = function () { 211 | var $parent = this.$element.closest('[data-toggle="buttons-radio"]') 212 | 213 | $parent && $parent 214 | .find('.active') 215 | .removeClass('active') 216 | 217 | this.$element.toggleClass('active') 218 | } 219 | 220 | 221 | /* BUTTON PLUGIN DEFINITION 222 | * ======================== */ 223 | 224 | var old = $.fn.button 225 | 226 | $.fn.button = function (option) { 227 | return this.each(function () { 228 | var $this = $(this) 229 | , data = $this.data('button') 230 | , options = typeof option == 'object' && option 231 | if (!data) $this.data('button', (data = new Button(this, options))) 232 | if (option == 'toggle') data.toggle() 233 | else if (option) data.setState(option) 234 | }) 235 | } 236 | 237 | $.fn.button.defaults = { 238 | loadingText: 'loading...' 239 | } 240 | 241 | $.fn.button.Constructor = Button 242 | 243 | 244 | /* BUTTON NO CONFLICT 245 | * ================== */ 246 | 247 | $.fn.button.noConflict = function () { 248 | $.fn.button = old 249 | return this 250 | } 251 | 252 | 253 | /* BUTTON DATA-API 254 | * =============== */ 255 | 256 | $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { 257 | var $btn = $(e.target) 258 | if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') 259 | $btn.button('toggle') 260 | }) 261 | 262 | }(window.jQuery);/* ========================================================== 263 | * bootstrap-carousel.js v2.3.2 264 | * http://getbootstrap.com/2.3.2/javascript.html#carousel 265 | * ========================================================== 266 | * Copyright 2013 Twitter, Inc. 267 | * 268 | * Licensed under the Apache License, Version 2.0 (the "License"); 269 | * you may not use this file except in compliance with the License. 270 | * You may obtain a copy of the License at 271 | * 272 | * http://www.apache.org/licenses/LICENSE-2.0 273 | * 274 | * Unless required by applicable law or agreed to in writing, software 275 | * distributed under the License is distributed on an "AS IS" BASIS, 276 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 277 | * See the License for the specific language governing permissions and 278 | * limitations under the License. 279 | * ========================================================== */ 280 | 281 | 282 | !function ($) { 283 | 284 | "use strict"; // jshint ;_; 285 | 286 | 287 | /* CAROUSEL CLASS DEFINITION 288 | * ========================= */ 289 | 290 | var Carousel = function (element, options) { 291 | this.$element = $(element) 292 | this.$indicators = this.$element.find('.carousel-indicators') 293 | this.options = options 294 | this.options.pause == 'hover' && this.$element 295 | .on('mouseenter', $.proxy(this.pause, this)) 296 | .on('mouseleave', $.proxy(this.cycle, this)) 297 | } 298 | 299 | Carousel.prototype = { 300 | 301 | cycle: function (e) { 302 | if (!e) this.paused = false 303 | if (this.interval) clearInterval(this.interval); 304 | this.options.interval 305 | && !this.paused 306 | && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 307 | return this 308 | } 309 | 310 | , getActiveIndex: function () { 311 | this.$active = this.$element.find('.item.active') 312 | this.$items = this.$active.parent().children() 313 | return this.$items.index(this.$active) 314 | } 315 | 316 | , to: function (pos) { 317 | var activeIndex = this.getActiveIndex() 318 | , that = this 319 | 320 | if (pos > (this.$items.length - 1) || pos < 0) return 321 | 322 | if (this.sliding) { 323 | return this.$element.one('slid', function () { 324 | that.to(pos) 325 | }) 326 | } 327 | 328 | if (activeIndex == pos) { 329 | return this.pause().cycle() 330 | } 331 | 332 | return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) 333 | } 334 | 335 | , pause: function (e) { 336 | if (!e) this.paused = true 337 | if (this.$element.find('.next, .prev').length && $.support.transition.end) { 338 | this.$element.trigger($.support.transition.end) 339 | this.cycle(true) 340 | } 341 | clearInterval(this.interval) 342 | this.interval = null 343 | return this 344 | } 345 | 346 | , next: function () { 347 | if (this.sliding) return 348 | return this.slide('next') 349 | } 350 | 351 | , prev: function () { 352 | if (this.sliding) return 353 | return this.slide('prev') 354 | } 355 | 356 | , slide: function (type, next) { 357 | var $active = this.$element.find('.item.active') 358 | , $next = next || $active[type]() 359 | , isCycling = this.interval 360 | , direction = type == 'next' ? 'left' : 'right' 361 | , fallback = type == 'next' ? 'first' : 'last' 362 | , that = this 363 | , e 364 | 365 | this.sliding = true 366 | 367 | isCycling && this.pause() 368 | 369 | $next = $next.length ? $next : this.$element.find('.item')[fallback]() 370 | 371 | e = $.Event('slide', { 372 | relatedTarget: $next[0] 373 | , direction: direction 374 | }) 375 | 376 | if ($next.hasClass('active')) return 377 | 378 | if (this.$indicators.length) { 379 | this.$indicators.find('.active').removeClass('active') 380 | this.$element.one('slid', function () { 381 | var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) 382 | $nextIndicator && $nextIndicator.addClass('active') 383 | }) 384 | } 385 | 386 | if ($.support.transition && this.$element.hasClass('slide')) { 387 | this.$element.trigger(e) 388 | if (e.isDefaultPrevented()) return 389 | $next.addClass(type) 390 | $next[0].offsetWidth // force reflow 391 | $active.addClass(direction) 392 | $next.addClass(direction) 393 | this.$element.one($.support.transition.end, function () { 394 | $next.removeClass([type, direction].join(' ')).addClass('active') 395 | $active.removeClass(['active', direction].join(' ')) 396 | that.sliding = false 397 | setTimeout(function () { that.$element.trigger('slid') }, 0) 398 | }) 399 | } else { 400 | this.$element.trigger(e) 401 | if (e.isDefaultPrevented()) return 402 | $active.removeClass('active') 403 | $next.addClass('active') 404 | this.sliding = false 405 | this.$element.trigger('slid') 406 | } 407 | 408 | isCycling && this.cycle() 409 | 410 | return this 411 | } 412 | 413 | } 414 | 415 | 416 | /* CAROUSEL PLUGIN DEFINITION 417 | * ========================== */ 418 | 419 | var old = $.fn.carousel 420 | 421 | $.fn.carousel = function (option) { 422 | return this.each(function () { 423 | var $this = $(this) 424 | , data = $this.data('carousel') 425 | , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) 426 | , action = typeof option == 'string' ? option : options.slide 427 | if (!data) $this.data('carousel', (data = new Carousel(this, options))) 428 | if (typeof option == 'number') data.to(option) 429 | else if (action) data[action]() 430 | else if (options.interval) data.pause().cycle() 431 | }) 432 | } 433 | 434 | $.fn.carousel.defaults = { 435 | interval: 5000 436 | , pause: 'hover' 437 | } 438 | 439 | $.fn.carousel.Constructor = Carousel 440 | 441 | 442 | /* CAROUSEL NO CONFLICT 443 | * ==================== */ 444 | 445 | $.fn.carousel.noConflict = function () { 446 | $.fn.carousel = old 447 | return this 448 | } 449 | 450 | /* CAROUSEL DATA-API 451 | * ================= */ 452 | 453 | $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { 454 | var $this = $(this), href 455 | , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 456 | , options = $.extend({}, $target.data(), $this.data()) 457 | , slideIndex 458 | 459 | $target.carousel(options) 460 | 461 | if (slideIndex = $this.attr('data-slide-to')) { 462 | $target.data('carousel').pause().to(slideIndex).cycle() 463 | } 464 | 465 | e.preventDefault() 466 | }) 467 | 468 | }(window.jQuery);/* ============================================================= 469 | * bootstrap-collapse.js v2.3.2 470 | * http://getbootstrap.com/2.3.2/javascript.html#collapse 471 | * ============================================================= 472 | * Copyright 2013 Twitter, Inc. 473 | * 474 | * Licensed under the Apache License, Version 2.0 (the "License"); 475 | * you may not use this file except in compliance with the License. 476 | * You may obtain a copy of the License at 477 | * 478 | * http://www.apache.org/licenses/LICENSE-2.0 479 | * 480 | * Unless required by applicable law or agreed to in writing, software 481 | * distributed under the License is distributed on an "AS IS" BASIS, 482 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 483 | * See the License for the specific language governing permissions and 484 | * limitations under the License. 485 | * ============================================================ */ 486 | 487 | 488 | !function ($) { 489 | 490 | "use strict"; // jshint ;_; 491 | 492 | 493 | /* COLLAPSE PUBLIC CLASS DEFINITION 494 | * ================================ */ 495 | 496 | var Collapse = function (element, options) { 497 | this.$element = $(element) 498 | this.options = $.extend({}, $.fn.collapse.defaults, options) 499 | 500 | if (this.options.parent) { 501 | this.$parent = $(this.options.parent) 502 | } 503 | 504 | this.options.toggle && this.toggle() 505 | } 506 | 507 | Collapse.prototype = { 508 | 509 | constructor: Collapse 510 | 511 | , dimension: function () { 512 | var hasWidth = this.$element.hasClass('width') 513 | return hasWidth ? 'width' : 'height' 514 | } 515 | 516 | , show: function () { 517 | var dimension 518 | , scroll 519 | , actives 520 | , hasData 521 | 522 | if (this.transitioning || this.$element.hasClass('in')) return 523 | 524 | dimension = this.dimension() 525 | scroll = $.camelCase(['scroll', dimension].join('-')) 526 | actives = this.$parent && this.$parent.find('> .accordion-group > .in') 527 | 528 | if (actives && actives.length) { 529 | hasData = actives.data('collapse') 530 | if (hasData && hasData.transitioning) return 531 | actives.collapse('hide') 532 | hasData || actives.data('collapse', null) 533 | } 534 | 535 | this.$element[dimension](0) 536 | this.transition('addClass', $.Event('show'), 'shown') 537 | $.support.transition && this.$element[dimension](this.$element[0][scroll]) 538 | } 539 | 540 | , hide: function () { 541 | var dimension 542 | if (this.transitioning || !this.$element.hasClass('in')) return 543 | dimension = this.dimension() 544 | this.reset(this.$element[dimension]()) 545 | this.transition('removeClass', $.Event('hide'), 'hidden') 546 | this.$element[dimension](0) 547 | } 548 | 549 | , reset: function (size) { 550 | var dimension = this.dimension() 551 | 552 | this.$element 553 | .removeClass('collapse') 554 | [dimension](size || 'auto') 555 | [0].offsetWidth 556 | 557 | this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') 558 | 559 | return this 560 | } 561 | 562 | , transition: function (method, startEvent, completeEvent) { 563 | var that = this 564 | , complete = function () { 565 | if (startEvent.type == 'show') that.reset() 566 | that.transitioning = 0 567 | that.$element.trigger(completeEvent) 568 | } 569 | 570 | this.$element.trigger(startEvent) 571 | 572 | if (startEvent.isDefaultPrevented()) return 573 | 574 | this.transitioning = 1 575 | 576 | this.$element[method]('in') 577 | 578 | $.support.transition && this.$element.hasClass('collapse') ? 579 | this.$element.one($.support.transition.end, complete) : 580 | complete() 581 | } 582 | 583 | , toggle: function () { 584 | this[this.$element.hasClass('in') ? 'hide' : 'show']() 585 | } 586 | 587 | } 588 | 589 | 590 | /* COLLAPSE PLUGIN DEFINITION 591 | * ========================== */ 592 | 593 | var old = $.fn.collapse 594 | 595 | $.fn.collapse = function (option) { 596 | return this.each(function () { 597 | var $this = $(this) 598 | , data = $this.data('collapse') 599 | , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) 600 | if (!data) $this.data('collapse', (data = new Collapse(this, options))) 601 | if (typeof option == 'string') data[option]() 602 | }) 603 | } 604 | 605 | $.fn.collapse.defaults = { 606 | toggle: true 607 | } 608 | 609 | $.fn.collapse.Constructor = Collapse 610 | 611 | 612 | /* COLLAPSE NO CONFLICT 613 | * ==================== */ 614 | 615 | $.fn.collapse.noConflict = function () { 616 | $.fn.collapse = old 617 | return this 618 | } 619 | 620 | 621 | /* COLLAPSE DATA-API 622 | * ================= */ 623 | 624 | $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { 625 | var $this = $(this), href 626 | , target = $this.attr('data-target') 627 | || e.preventDefault() 628 | || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 629 | , option = $(target).data('collapse') ? 'toggle' : $this.data() 630 | $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 631 | $(target).collapse(option) 632 | }) 633 | 634 | }(window.jQuery);/* ============================================================ 635 | * bootstrap-dropdown.js v2.3.2 636 | * http://getbootstrap.com/2.3.2/javascript.html#dropdowns 637 | * ============================================================ 638 | * Copyright 2013 Twitter, Inc. 639 | * 640 | * Licensed under the Apache License, Version 2.0 (the "License"); 641 | * you may not use this file except in compliance with the License. 642 | * You may obtain a copy of the License at 643 | * 644 | * http://www.apache.org/licenses/LICENSE-2.0 645 | * 646 | * Unless required by applicable law or agreed to in writing, software 647 | * distributed under the License is distributed on an "AS IS" BASIS, 648 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 649 | * See the License for the specific language governing permissions and 650 | * limitations under the License. 651 | * ============================================================ */ 652 | 653 | 654 | !function ($) { 655 | 656 | "use strict"; // jshint ;_; 657 | 658 | 659 | /* DROPDOWN CLASS DEFINITION 660 | * ========================= */ 661 | 662 | var toggle = '[data-toggle=dropdown]' 663 | , Dropdown = function (element) { 664 | var $el = $(element).on('click.dropdown.data-api', this.toggle) 665 | $('html').on('click.dropdown.data-api', function () { 666 | $el.parent().removeClass('open') 667 | }) 668 | } 669 | 670 | Dropdown.prototype = { 671 | 672 | constructor: Dropdown 673 | 674 | , toggle: function (e) { 675 | var $this = $(this) 676 | , $parent 677 | , isActive 678 | 679 | if ($this.is('.disabled, :disabled')) return 680 | 681 | $parent = getParent($this) 682 | 683 | isActive = $parent.hasClass('open') 684 | 685 | clearMenus() 686 | 687 | if (!isActive) { 688 | if ('ontouchstart' in document.documentElement) { 689 | // if mobile we we use a backdrop because click events don't delegate 690 | $('