Angular项目构建指南 - 不再为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自己会去处理.
angular.module('myApp', [
  'ngRoute',
]);
例如这里的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
'use strict';


// Declare app level module which depends on filters, and services
angular.module('myApp', [
  'ngRoute',
  'myApp.filters',
  'myApp.services',
  'myApp.directives',
  'myApp.controllers'
]).
config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view1', {templateUrl: 'partials/partial1.html', controller: 'MyCtrl1'});
  $routeProvider.when('/view2', {templateUrl: 'partials/partial2.html', controller: 'MyCtrl2'});
  $routeProvider.otherwise({redirectTo: '/view1'});
}]);
controllers.js
'use strict';

/* Controllers */

angular.module('myApp.controllers', [])
  .controller('MyCtrl1', ['$scope', function($scope) {

  }])
  .controller('MyCtrl2', ['$scope', function($scope) {

  }]);
directives.js
'use strict';

/* Directives */


angular.module('myApp.directives', []).
  directive('appVersion', ['version', function(version) {
    return function(scope, elm, attrs) {
      elm.text(version);
    };
  }]);
filters.js
'use strict';

/* Filters */

angular.module('myApp.filters', []).
  filter('interpolate', ['version', function(version) {
    return function(text) {
      return String(text).replace(/\%VERSION\%/mg, version);
    };
  }]);
services.js
'use strict';

/* Services */


// Demonstrate how to register services
// In this case it is a simple value service.
angular.module('myApp.services', []).
  value('version', '0.1');
index.html
<!DOCTYPE html>
<!--[if lt IE 7]>      <html ng-app="myApp" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html ng-app="myApp" class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html ng-app="myApp" class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html ng-app="myApp"> <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>My AngularJS App</title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="bower_components/html5-boilerplate/css/normalize.css">
  <link rel="stylesheet" href="bower_components/html5-boilerplate/css/main.css">
  <link rel="stylesheet" href="css/app.css"/>
  <script src="bower_components/html5-boilerplate/js/vendor/modernizr-2.6.2.min.js"></script>
</head>
<body>
  <ul>
    <li><a href="#/view1">view1</a></li>
    <li><a href="#/view2">view2</a></li>
  </ul>

  <!--[if lt IE 7]>
      <p>You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
  <![endif]-->

  <div ng-view></div>

  <div>Angular seed app: v<span app-version></span></div>

  <!-- In production use:
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script>
  -->
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
  <script src="js/app.js"></script>
  <script src="js/services.js"></script>
  <script src="js/controllers.js"></script>
  <script src="js/filters.js"></script>
  <script src="js/directives.js"></script>
</body>
</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

<!doctype html>
<html ng-app>
<head>
<title>Angular-RequireJS sample app</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" media="all" href="app/css/app.css" />
</head>
<body >
<h1>AngularJS + RequireJS</h1>
<ul>
<li><a href="#/view1">View 1</a></li>
<li><a href="#/view2">View 2</a></li>
</ul>
<div ng-view></div>
<script data-main="app/js/main" src="/bower_components/requirejs/require.js"></script>
</body>
</html>
    main.js

require.config({
    paths: {
        angular: '../../bower_components/angular/angular',
        angularRoute: '../../bower_components/angular-route/angular-route',
        angularMocks: '../../bower_components/angular-mocks/angular-mocks',
        text: '../../bower_components/requirejs-text/text'
    },
    shim: {
        'angular' : {'exports' : 'angular'},
        'angularRoute': ['angular'],
        'angularMocks': {
            deps:['angular'],
            'exports':'angular.mock'
        }
    },
    priority: [
        "angular"
    ]
});

//http://code.angularjs.org/1.2.1/docs/guide/bootstrap#overview_deferred-bootstrap
window.name = "NG_DEFER_BOOTSTRAP!";

require( [
    'angular',
    'app',
    'routes'
], function(angular, app, routes) {
    'use strict';
    var $html = angular.element(document.getElementsByTagName('html')[0]);

    angular.element().ready(function() {
        angular.resumeBootstrap([app['name']]);
    });
});
app.js
define([
    'angular',
    'filters',
    'services',
    'directives',
    'controllers',
    'angularRoute',
    ], function (angular, filters, services, directives, controllers) {
        'use strict';

        // Declare app level module which depends on filters, and services
        
        return angular.module('myApp', [
            'ngRoute',
            'myApp.controllers',
            'myApp.filters',
            'myApp.services',
            'myApp.directives'
        ]);
});
controllers.js
define(['angular', 'services'], function (angular) {
    'use strict';

    /* Controllers */
    
    return angular.module('myApp.controllers', ['myApp.services'])
        // Sample controller where service is being used
        .controller('MyCtrl1', ['$scope', 'version', function ($scope, version) {
            $scope.scopedAppVersion = version;
        }])
        // More involved example where controller is required from an external file
        .controller('MyCtrl2', ['$scope', '$injector', function($scope, $injector) {
            require(['controllers/myctrl2'], function(myctrl2) {
                // injector method takes an array of modules as the first argument
                // if you want your controller to be able to use components from
                // any of your other modules, make sure you include it together with 'ng'
                // Furthermore we need to pass on the $scope as it's unique to this controller
                $injector.invoke(myctrl2, this, {'$scope': $scope});
            });
        }]);
});
directives.js
define(['angular', 'services'], function(angular, services) {
    'use strict';

  /* Directives */

    angular.module('myApp.directives', ['myApp.services'])
        .directive('appVersion', ['version', function(version) {
            return function(scope, elm, attrs) {
                elm.text(version);
        };
    }]);
});
filters.js
define(['angular', 'services'], function (angular, services) {
    'use strict';

    /* Filters */
  
    angular.module('myApp.filters', ['myApp.services'])
        .filter('interpolate', ['version', function(version) {
            return function(text) {
                return String(text).replace(/\%VERSION\%/mg, version);
            };
    }]);
});
routes.js
define(['angular', 'app'], function(angular, app) {
    'use strict';

    return app.config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/view1', {
            templateUrl: 'app/partials/partial1.html',
            controller: 'MyCtrl1'
        });
        $routeProvider.when('/view2', {
            templateUrl: 'app/partials/partial2.html',
            controller: 'MyCtrl2'
        });
        $routeProvider.otherwise({redirectTo: '/view1'});
    }]);

});
services.js
define(['angular'], function (angular) {
    'use strict';
    
  /* Services */

  // Demonstrate how to register services
  // In this case it is a simple value service.
    angular.module('myApp.services', [])
        .value('version', '0.1');
});
    controllers文件夹中一个单独controlle文件,myCtrl2.js

define([], function() {
    return ['$scope', '$http', function($scope, $http) {
        // You can access the scope of the controller from here
        $scope.welcomeMessage = 'hey this is myctrl2.js!';

        // because this has happened asynchroneusly we've missed
        // Angular's initial call to $apply after the controller has been loaded
        // hence we need to explicityly call it at the end of our Controller constructor
        $scope.$apply();
    }];
});

结尾

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

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
3.将maven项目jar纳入maven仓库,Mave项目依赖另外一个Maven项目的案例
 1 若想让maven项目依赖另外一个maven项目,被依赖的项目要在maven仓库中有相应的jar包,所以要对依赖的项目执行mvninstall命令。 2 新建第二个项目模块HelloFriend目录及约定的目录结构 HelloFriend  --src  -----main  ----------java
1165 0
走进JavaWeb技术世界12:从手动编译打包到项目构建工具Maven
本文出自我的公众号:程序员江湖。 满满干货,关注就送。 小李的Build之路(上) 转自: 刘欣 码农翻身 2016-07-10 摘要:手工Build的烦恼要不是为了和女朋友留在一个城市,小李肯定去北上广奋斗去了。
1658 0
菜鸟入门【ASP.NET Core】8:Middleware管道介绍、自己动手构建RequestDelegate管道
中间件:是汇集到以处理请求和响应的一个应用程序管道的软件。 每个组件: 可以选择是否要将请求传递到管道中的下一个组件。 之前和之后调用管道中的下一个组件,可以执行工作。 使用请求委托来生成请求管道。
1244 0
【项目启动】 tomcat启动,项目无法启动,无法正常访问/项目可以启动,报错:java.lang.ClassNotFoundException: ContextLoaderListener
使用maven搭建项目(这个错误和是不是使用maven搭建项目没有关系),然后部署到tomcat中运行。   出现问题1: tomcat跑起来了,但是启动时间很短,没有报错,项目不能正常访问 项目启动时间很短,并且没有报错 并且项目无法正常访问   发现问题过程: 查看tomcat下,发现这个项目在tomcat的webapps下部署的仅仅是项目的部分文件,有好多的东西并没有部署进来 我们发现tomcat下部署的本项目中 并没有lib依赖包库 等目录。
1816 0
VMware顺容器之势而为,发布开源项目Lightwave和Photon
本文讲的是VMware顺容器之势而为,发布开源项目Lightwave和Photon,【编者的话】VMware是老牌的虚拟化技术提供商,但Docker等容器技术对其核心业务造成了不小的冲击,为了应付这种冲击,并顺应潮流,VMware发布了两个新的开源项目,Project Lightwave和Project Photon,这两个项目都是致力于提高云应用以及企业架构的扩展性。
1145 0
在 GitHub 上构建一个看上去正规的 Golang 项目
接触 golang 时间很长,但是真正动手开始写 golang 也就是在最近。跟着我在 GitHub 上构建一个看上去正规的 Golang 项目。
5668 0
【maven 报错】maven项目执行maven install时报错Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode)
在使用maven新建的web项目中,执行   执行如上的这两个操作,报错: 1 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.
2727 0
IBM RSA (IBM rational software architect ) V8 学习之二 新建项目
原文http://blog.csdn.net/ztz0223/article/details/7592253 这类文章只是我自己需要,所以学习了,自己的一些操作,特地记录下来。看客若有更好的见解,欢迎提出,先表示感谢。
804 0
艾伟也谈项目管理,Richard Durnall谈系统管理和从外向内的组织结构
  InfoQ中文站:能给我们介绍一下“系统管理理论”(System Management Theory)么?能不能跟我们分享一下您在实际应用中的经验?   Richard Durnall:系统管理理论是过去五十年里出现并逐步发展而来的。
924 0
+关注
3598
文章
840
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载