Angular项目构建指南:不再为angular构建而犹豫不决

开发 开发工具 前端
洋洋洒洒写了一大堆都是最近构建项目的一些经验,对于angular项目的构建确实不大同于以往的前端框架,所以特此记录分享给大家,希望有所帮助。

前言

接触Angular也有小半个月了,虽然没有使劲折腾,不过正所谓"no zuo no die".学一门新东西,不好好折腾一下总觉得对不起祖国,最不起人民...好像扯远了,想写前言来着.为什么要写这篇构建指南?***的原因是为了给正在找这方面资料,挣扎于各种说法中的同学一个借鉴,同时我也把自己的经验记录下来,两全其美.

正文

如果你不知道什么是Angular或者根本没听说过,那么我接下来所说的对你来说毫无益处,不过如果你打算以后会接触Angular或者干脆要涨涨姿势~读下去还是有点用的.

Angular和它之前所出现的其余前端框架***的不同,在于它的核心不再是DOM,而是数据,是model.我们惯用的不管是单纯的jQuery还是MVC的Backbone,它们本质仍是让我们更方便更有条理的操作DOM,但是Angular不是.通过一系列魔术般的手法,它将一切的重心转移到数据上.以开发应用而不是操作节点的方式去开发Web,一切以数据为中心,数据的变化驱动了一切,包括行为.

文本主题,如何构建一个angular项目?

坦白说最开始构建一个项目的时候,虽然很小但是很纠结.我本身是有点***主义的,所以虽然一开始什么都没有也想做到尽善尽美.因为听过很多前辈的经验,说如果框架基础没搭好,等到后来不管是重构还是维护都是一场噩梦.所以一开始小心意义,希望能将项目尽量搭建的结实并且益于维护和开发.

在搭建伊始首先遇到的一个问题,就是到底要不要引入requirejs或者seajs这类依赖管理的工具?

我本身没有多少语言或者技术的上的情节,对于各个大神也没有多少膜拜的憧憬(更多的是我根本不清楚谁是大神,也从没去找过).所以对于我来讲不管是requirejs的AMD还是seajs的CMD,从实现的角度上来讲都是做了同一个工作.在考虑一个Angular应用到底需不需要这种工具的时候,我也在网上看了很多人的说法.我总结一句就是,基本都和没说一样,也就是用不用随便,看情况.

那么我能有什么好的答案,其实我现在的答案就是:"可以不用".怎么说是可以不用呢,如果你不用requirejs也能满足项目的开发以及各种需求,那么就别用了.angular本身的模块已经做到了依赖注入,所以我们不需要通过requirejs进行异步加载也可以很好的用下去.

当然,如果你开发过程中发觉还是有些地方需要,那么也可以加上去.本文里我会详细说明这两种方式的构建方法.但是这里我的观点已经表明了:在不需要的情况下,不要用.

(1) 不用requirejs直接构建Angular

之所以不使用requirejs就直接构建angular,因为angular对于依赖的管理以及angular的使用场景完全可以做到这一点.首先在以来上,angular的依赖注入是个好东西,不了解的同学可以去搜一下资料.我这里简单的说,就是当我需要一个module的时候,我不用管它在哪,它是什么.我只要知道它的名字然后告诉angular就可以了,至于怎么将它的对象传递过来,怎么找到的,angular自己会去处理.

  1. angular.module('myApp', [  
  2.   'ngRoute',  
  3. ]); 

例如这里的ngRoute,我需要知道ngRoute怎么来的,在哪里.只要有一个模块定义为ngRoute我就可以直接拿来用。

鉴于Angular如此的给力,剩下的事情就好办了.我们只需要从功能和业务两方面将文件划分成module就可以了,然后将所有的库文件在页面上通过script标签引用,再将所有的业务文件也即是我们自己写的js合并为一个all.js加载到页面上即可。

这里文件的划分遵循angular官方的推荐方式:

|--js
   |--app.js                     // app启动文件,用于app配置
   |--controllers.js          // controllers也就是存放我们自己的业务文件
   |--directives.js            // 指令文件(指令可共用)
   |--fliters.js                  // 过滤器文件(过滤器可共用)
   |--services.js             //  服务文件(可共用,一般是与服务器交互的服务)
|--partials
   |--html1.html  
   |--html2.html
|--index.html

app.js

  1. 'use strict';  
  2.  
  3.  
  4. // Declare app level module which depends on filters, and services  
  5. angular.module('myApp', [  
  6.   'ngRoute',  
  7.   'myApp.filters',  
  8.   'myApp.services',  
  9.   'myApp.directives',  
  10.   'myApp.controllers' 
  11. ]).  
  12. config(['$routeProvider'function($routeProvider) {  
  13.   $routeProvider.when('/view1', {templateUrl: 'partials/partial1.html', controller: 'MyCtrl1'});  
  14.   $routeProvider.when('/view2', {templateUrl: 'partials/partial2.html', controller: 'MyCtrl2'});  
  15.   $routeProvider.otherwise({redirectTo: '/view1'});  
  16. }]); 

controllers.js

  1. 'use strict';  
  2.  
  3. /* Controllers */ 
  4.  
  5. angular.module('myApp.controllers', [])  
  6.   .controller('MyCtrl1', ['$scope'function($scope) {  
  7.  
  8.   }])  
  9.   .controller('MyCtrl2', ['$scope'function($scope) {  
  10.  
  11.   }]); 

directives.js

  1. 'use strict';  
  2.  
  3. /* Directives */ 
  4.  
  5.  
  6. angular.module('myApp.directives', []).  
  7.   directive('appVersion', ['version'function(version) {  
  8.     return function(scope, elm, attrs) {  
  9.       elm.text(version);  
  10.     };  
  11.   }]); 

filters.js

  1. 'use strict';  
  2.  
  3. /* Filters */ 
  4.  
  5. angular.module('myApp.filters', []).  
  6.   filter('interpolate', ['version'function(version) {  
  7.     return function(text) {  
  8.       return String(text).replace(/\%VERSION\%/mg, version);  
  9.     };  
  10.   }]); 

services.js

  1. 'use strict';  
  2.  
  3. /* Services */ 
  4.  
  5.  
  6. // Demonstrate how to register services  
  7. // In this case it is a simple value service.  
  8. angular.module('myApp.services', []).  
  9.   value('version''0.1'); 

index.html

  1. <!DOCTYPE html> 
  2. <!--[if lt IE 7]>      <html ng-app="myApp" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> 
  3. <!--[if IE 7]>         <html ng-app="myApp" class="no-js lt-ie9 lt-ie8"> <![endif]--> 
  4. <!--[if IE 8]>         <html ng-app="myApp" class="no-js lt-ie9"> <![endif]--> 
  5. <!--[if gt IE 8]><!--> <html ng-app="myApp"> <!--<![endif]--> 
  6. <head> 
  7.   <meta charset="utf-8"> 
  8.   <meta http-equiv="X-UA-Compatible" content="IE=edge"> 
  9.   <title>My AngularJS App</title> 
  10.   <meta name="description" content=""> 
  11.   <meta name="viewport" content="width=device-width, initial-scale=1"> 
  12.   <link rel="stylesheet" href="bower_components/html5-boilerplate/css/normalize.css"> 
  13.   <link rel="stylesheet" href="bower_components/html5-boilerplate/css/main.css"> 
  14.   <link rel="stylesheet" href="css/app.css"/> 
  15.   <script src="bower_components/html5-boilerplate/js/vendor/modernizr-2.6.2.min.js"></script> 
  16. </head> 
  17. <body> 
  18.   <ul> 
  19.     <li><a href="#/view1">view1</a></li> 
  20.     <li><a href="#/view2">view2</a></li> 
  21.   </ul> 
  22.  
  23.   <!--[if lt IE 7]> 
  24.       <p>You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> 
  25.   <![endif]--> 
  26.  
  27.   <div ng-view></div> 
  28.  
  29.   <div>Angular seed app: v<span app-version></span></div> 
  30.  
  31.   <!-- In production use:  
  32.   <script src="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script> 
  33.   --> 
  34.   <script src="bower_components/angular/angular.js"></script> 
  35.   <script src="bower_components/angular-route/angular-route.js"></script> 
  36.   <script src="js/app.js"></script> 
  37.   <script src="js/services.js"></script> 
  38.   <script src="js/controllers.js"></script> 
  39.   <script src="js/filters.js"></script> 
  40.   <script src="js/directives.js"></script> 
  41. </body> 
  42. </html> 

如此在不使用requirejs的情景下,项目就构建完成了.还有几个补充点就是其一你可以将controllers继续拆分为多个controller模块,这里可以完全按照你的业务进行划分.比如user目录下userController等等.然后将所有这些我们自己写的文件通过grunt或者gulp进行合并为一个单独的总的文件all.js这样在页面中除了库文件只要这一个文件就行了.angular的module所带来的好处就是这样合并的文件,不用在乎js合并的顺序,因为它是通过angular依赖注入的。

(2) 通过requirejs构建

这种方式的构建可能对于某些人来讲更加清晰,结构和上面的基本一样,多了一个man.js用来配置requirejs,单独拆分出routes.js以及一个controller文件夹通过requirejs将controller一个个拆分出来,按需的异步加载。

index.html

  1. <!doctype html> 
  2. <html ng-app> 
  3. <head> 
  4. <title>Angular-RequireJS sample app</title> 
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
  6. <link rel="stylesheet" type="text/css" media="all" href="app/css/app.css" /> 
  7. </head> 
  8. <body > 
  9. <h1>AngularJS + RequireJS</h1> 
  10. <ul> 
  11. <li><a href="#/view1">View 1</a></li> 
  12. <li><a href="#/view2">View 2</a></li> 
  13. </ul> 
  14. <div ng-view></div> 
  15. <script data-main="app/js/main" src="/bower_components/requirejs/require.js"></script> 
  16. </body> 
  17. </html> 

#p#

main.js

  1. require.config({  
  2.     paths: {  
  3.         angular: '../../bower_components/angular/angular',  
  4.         angularRoute: '../../bower_components/angular-route/angular-route',  
  5.         angularMocks: '../../bower_components/angular-mocks/angular-mocks',  
  6.         text: '../../bower_components/requirejs-text/text' 
  7.     },  
  8.     shim: {  
  9.         'angular' : {'exports' : 'angular'},  
  10.         'angularRoute': ['angular'],  
  11.         'angularMocks': {  
  12.             deps:['angular'],  
  13.             'exports':'angular.mock' 
  14.         }  
  15.     },  
  16.     priority: [  
  17.         "angular" 
  18.     ]  
  19. });  
  20.  
  21. //http://code.angularjs.org/1.2.1/docs/guide/bootstrap#overview_deferred-bootstrap  
  22. window.name = "NG_DEFER_BOOTSTRAP!";  
  23.  
  24. require( [  
  25.     'angular',  
  26.     'app',  
  27.     'routes' 
  28. ], function(angular, app, routes) {  
  29.     'use strict';  
  30.     var $html = angular.element(document.getElementsByTagName('html')[0]);  
  31.  
  32.     angular.element().ready(function() {  
  33.         angular.resumeBootstrap([app['name']]);  
  34.     });  
  35. }); 

app.js

  1. define([  
  2.     'angular',  
  3.     'filters',  
  4.     'services',  
  5.     'directives',  
  6.     'controllers',  
  7.     'angularRoute',  
  8.     ], function (angular, filters, services, directives, controllers) {  
  9.         'use strict';  
  10.  
  11.         // Declare app level module which depends on filters, and services  
  12.           
  13.         return angular.module('myApp', [  
  14.             'ngRoute',  
  15.             'myApp.controllers',  
  16.             'myApp.filters',  
  17.             'myApp.services',  
  18.             'myApp.directives' 
  19.         ]);  
  20. }); 

controllers.js

  1. define(['angular''services'], function (angular) {  
  2.     'use strict';  
  3.  
  4.     /* Controllers */ 
  5.       
  6.     return angular.module('myApp.controllers', ['myApp.services'])  
  7.         // Sample controller where service is being used  
  8.         .controller('MyCtrl1', ['$scope''version'function ($scope, version) {  
  9.             $scope.scopedAppVersion = version;  
  10.         }])  
  11.         // More involved example where controller is required from an external file  
  12.         .controller('MyCtrl2', ['$scope''$injector'function($scope, $injector) {  
  13.             require(['controllers/myctrl2'], function(myctrl2) {  
  14.                 // injector method takes an array of modules as the first argument  
  15.                 // if you want your controller to be able to use components from  
  16.                 // any of your other modules, make sure you include it together with 'ng'  
  17.                 // Furthermore we need to pass on the $scope as it's unique to this controller  
  18.                 $injector.invoke(myctrl2, this, {'$scope': $scope});  
  19.             });  
  20.         }]);  
  21. }); 

directives.js

  1. define(['angular''services'], function(angular, services) {  
  2.     'use strict';  
  3.  
  4.   /* Directives */ 
  5.  
  6.     angular.module('myApp.directives', ['myApp.services'])  
  7.         .directive('appVersion', ['version'function(version) {  
  8.             return function(scope, elm, attrs) {  
  9.                 elm.text(version);  
  10.         };  
  11.     }]);  
  12. }); 

filters.js

  1. define(['angular''services'], function (angular, services) {  
  2.     'use strict';  
  3.  
  4.     /* Filters */ 
  5.     
  6.     angular.module('myApp.filters', ['myApp.services'])  
  7.         .filter('interpolate', ['version'function(version) {  
  8.             return function(text) {  
  9.                 return String(text).replace(/\%VERSION\%/mg, version);  
  10.             };  
  11.     }]);  
  12. }); 

routes.js

  1. define(['angular''app'], function(angular, app) {  
  2.     'use strict';  
  3.  
  4.     return app.config(['$routeProvider'function($routeProvider) {  
  5.         $routeProvider.when('/view1', {  
  6.             templateUrl: 'app/partials/partial1.html',  
  7.             controller: 'MyCtrl1' 
  8.         });  
  9.         $routeProvider.when('/view2', {  
  10.             templateUrl: 'app/partials/partial2.html',  
  11.             controller: 'MyCtrl2' 
  12.         });  
  13.         $routeProvider.otherwise({redirectTo: '/view1'});  
  14.     }]);  
  15.  
  16. }); 

services.js

  1. define(['angular'], function (angular) {  
  2.     'use strict';  
  3.       
  4.   /* Services */ 
  5.  
  6.   // Demonstrate how to register services  
  7.   // In this case it is a simple value service.  
  8.     angular.module('myApp.services', [])  
  9.         .value('version''0.1');  
  10. }); 

controllers文件夹中一个单独controlle文件,myCtrl2.js

  1. define([], function() {  
  2.     return ['$scope''$http'function($scope, $http) {  
  3.         // You can access the scope of the controller from here  
  4.         $scope.welcomeMessage = 'hey this is myctrl2.js!';  
  5.  
  6.         // because this has happened asynchroneusly we've missed  
  7.         // Angular's initial call to $apply after the controller has been loaded  
  8.         // hence we need to explicityly call it at the end of our Controller constructor  
  9.         $scope.$apply();  
  10.     }];  
  11. }); 

结尾

写到这应该差不多了,就快超字数了.通常情况下Angular应用的构建这样就可以了,因为比起传统框架angular的代码量上肯定会有优势,所以一些不必要的东西就不用引入了.上面这些也是我在这段时间的项目中遇到并且做过的,已经实战过了,所以如果有类似需求的同学可以不必在此填坑。

***留个彩蛋吧,在不用requirejs的情况下,angular也是可以实现异步加载的,只要通过一个非常小巧的库就可以,名字叫script.js.https://github.com/ded/script.js

责任编辑:林师授 来源: oschina博客
相关推荐

2020-05-29 22:19:07

物联网IOT物联网技术

2014-09-19 14:40:08

2014-09-29 09:31:35

Angular

2019-03-10 08:36:23

物联网 IoT投资

2010-04-16 12:44:17

Oracle数据库表

2009-10-22 16:32:10

布线系统短链路问题

2020-12-09 14:37:43

Travis CI开源免费

2017-11-28 18:33:30

机器学习人工智能金融

2023-08-28 13:40:00

CIO数字化转型

2023-10-23 11:04:04

2023-03-27 16:35:43

AI作图工具安全

2024-03-01 19:53:37

PyBuilderPython开发

2024-05-17 17:29:00

CurdlingPython开发

2018-08-02 11:31:15

小说

2010-06-01 09:16:26

数据中心功耗

2024-01-15 06:11:13

Go构建器模式开发

2018-07-25 09:49:59

2017-06-26 15:10:00

Linux桌面系统系统优势

2010-09-29 09:59:27

2014-07-23 10:08:34

Angular前端项目
点赞
收藏

51CTO技术栈公众号