原文出处:https://my.oschina.net/blogshi/blog/280400

摘要: 洋洋洒洒写了一大堆都是最近构建项目的一些经验,对于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

'usestrict';


//Declareapplevelmodulewhichdependsonfilters,andservices
angular.module('myApp','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

'usestrict';

/*Controllers*/

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

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

}]);

directives.js

'usestrict';

/*Directives*/


angular.module('myApp.directives',[]).
directive('appVersion',['version',function(version){
returnfunction(scope,elm,attrs){
elm.text(version);
};
}]);

filters.js

'usestrict';

/*Filters*/

angular.module('myApp.filters',[]).
filter('interpolate',function(version){
returnfunction(text){
returnString(text).replace(/\%VERSION\%/mg,version);
};
}]);

services.js

'usestrict';

/*Services*/


//Demonstratehowtoregisterservices
//Inthiscaseitisasimplevalueservice.
angular.module('myApp.services',[]).
value('version','0.1');

index.html

<!DOCTYPEhtml>
<!--[ifltIE7]><htmlng-app="myApp"class="no-jslt-ie9lt-ie8lt-ie7"><![endif]-->
<!--[ifIE7]><htmlng-app="myApp"class="no-jslt-ie9lt-ie8"><![endif]-->
<!--[ifIE8]><htmlng-app="myApp"class="no-jslt-ie9"><![endif]-->
<!--[ifgtIE8]><!--><htmlng-app="myApp"><!--<![endif]-->
<head>
<Metacharset="utf-8">
<Metahttp-equiv="X-UA-Compatible"content="IE=edge">
<title>MyAngularJSApp</title>
<Metaname="description"content="">
<Metaname="viewport"content="width=device-width,initial-scale=1">
<linkrel="stylesheet"href="bower_components/html5-boilerplate/css/normalize.css">
<linkrel="stylesheet"href="bower_components/html5-boilerplate/css/main.css">
<linkrel="stylesheet"href="css/app.css"/>
<scriptsrc="bower_components/html5-boilerplate/js/vendor/modernizr-2.6.2.min.js"></script>
</head>
<body>
<ul>
<li><ahref="#/view1">view1</a></li>
<li><ahref="#/view2">view2</a></li>
</ul>

<!--[ifltIE7]> <p>Youareusingan<strong>outdated</strong>browser.Please<ahref="http://browsehappy.com/">upgradeyourbrowser</a>toimproveyourexperience.</p> <![endif]-->

<divng-view></div>

<div>Angularseedapp:v<spanapp-version></span></div>

<!--Inproductionuse: <scriptsrc="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script> -->
<scriptsrc="bower_components/angular/angular.js"></script>
<scriptsrc="bower_components/angular-route/angular-route.js"></script>
<scriptsrc="js/app.js"></script>
<scriptsrc="js/services.js"></script>
<scriptsrc="js/controllers.js"></script>
<scriptsrc="js/filters.js"></script>
<scriptsrc="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

<!doctypehtml>
<htmlng-app>
<head>
<title>Angular-RequireJSsampleapp</title>
<Metaname="viewport"content="width=device-width,initial-scale=1.0">
<linkrel="stylesheet"type="text/css"media="all"href="app/css/app.css"/>
</head>
<body>
<h1>AngularJS+RequireJS</h1>
<ul>
<li><ahref="#/view1">View1</a></li>
<li><ahref="#/view2">View2</a></li>
</ul>
<divng-view></div>
<scriptdata-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){
	'usestrict';
	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){
		'usestrict';

		//Declareapplevelmodulewhichdependsonfilters,andservices
		
		returnangular.module('myApp',[
			'ngRoute','myApp.controllers','myApp.directives'
		]);
});

controllers.js

define(['angular','services'],function(angular){
	'usestrict';

	/*Controllers*/
	
	returnangular.module('myApp.controllers',['myApp.services'])
		//Samplecontrollerwhereserviceisbeingused
		.controller('MyCtrl1','version',function($scope,version){
			$scope.scopedAppVersion=version;
		}])
		//Moreinvolvedexamplewherecontrollerisrequiredfromanexternalfile
		.controller('MyCtrl2','$injector',function($scope,$injector){
			require(['controllers/myctrl2'],function(myctrl2){
				//injectormethodtakesanarrayofmodulesasthefirstargument
				//ifyouwantyourcontrollertobeabletousecomponentsfrom
				//anyofyourothermodules,makesureyouincludeittogetherwith'ng'
				//Furthermoreweneedtopassonthe$scopeasit'suniquetothiscontroller
				$injector.invoke(myctrl2,this,{'$scope':$scope});
			});
		}]);
});

directives.js

define(['angular',function(angular,services){
	'usestrict';

/*Directives*/

	angular.module('myApp.directives',['myApp.services'])
		.directive('appVersion',function(version){
			returnfunction(scope,attrs){
				elm.text(version);
		};
	}]);
});

filters.js

define(['angular',services){
	'usestrict';

	/*Filters*/

	angular.module('myApp.filters',['myApp.services'])
		.filter('interpolate',function(version){
			returnfunction(text){
				returnString(text).replace(/\%VERSION\%/mg,version);
			};
	}]);
});

routes.js

define(['angular','app'],app){
	'usestrict';

	returnapp.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){
	'usestrict';
	
/*Services*/

//Demonstratehowtoregisterservices
//Inthiscaseitisasimplevalueservice.
	angular.module('myApp.services',[])
		.value('version','0.1');
});

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

define([],function(){
	return['$scope','$http',$http){
		//Youcanaccessthescopeofthecontrollerfromhere
		$scope.welcomeMessage='heythisismyctrl2.js!';

		//becausethishashappenedasynchroneuslywe'vemissed
		//Angular'sinitialcallto$applyafterthecontrollerhasbeenloaded
		//henceweneedtoexplicitylycallitattheendofourControllerconstructor
		$scope.$apply();
	}];
});

结尾

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

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

Angular项目构建指南 - 不再为angular构建而犹豫不决的更多相关文章

  1. html5 拖拽及用 js 实现拖拽功能的示例代码

    这篇文章主要介绍了html5 拖拽及用 js 实现拖拽,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. swift皮筋弹动发射飞机ios源码

    这是一个款采用swift实现的皮筋弹动发射飞机游戏源码,游戏源码比较详细,大家可以研究学习一下吧。

  4. Swift与Js通过WebView交互

    开发环境:Swfit2.3XCode8.2基础概念jscontext,jscontext是代表JS的执行环境,通过-evaluateScript:方法就可以执行一JS代码JSValue,JSValue封装了JS与ObjC中的对应的类型,以及调用JS的API等JSExport,JSExport是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,才能调用Swif

  5. JSCore swift

    如果双方相互引用,会造成循环引用,而导致内存泄露。以上是Jscore的基本使用,比较简单

  6. Swift WKWebView的js调用swift

    最近项目需求,需要用到JavaScriptCore和WebKit,但是网上的资源有限,而且比较杂,都是一个博客复制另外一个博客,都没有去实际敲代码验证,下面给大家分享一下我的学习过程。

  7. Swift WKWebView的swift调用js

    不多说,直接上代码:在html里面要添加的的代码,显示swift传过去的参数:这样就实现了swift给js传参数和调用!

  8. 在 Swift 專案中使用 Javascript:編寫一個將 Markdown 轉為 HTML 的編輯器

    你有強烈的好奇心,希望在你的iOS專案中使用JavaScript。jscontext中的所有值都是JSValue對象,JSValue類用於表示任意類型的JavaScript值。因此,我們既需要寫Swift代碼也要寫JavaScript代碼。此外,我們還會在JavaScript中按照這個類的定義來創建一個對象并對其屬性進行賦值。從Swift中呼叫JavaScript就如介紹中所言,JavaScriptCore中最主要的角色就是jscontext類。一個jscontext對象是位於JavaScript環境和本

  9. swift - WKWebView JS 交互

    本文介绍WKWebView怎么与js交互,至于怎么用WKWebView这里就不介绍了HTML代码APP调JS代码结果JS给APP传参数首先注册你需要监听的js方法名2.继承WKScriptMessageHandler并重写userContentController方法,在该方法里接收JS传来的参数3.结果

  10. swift 开发UIWebView跟JS的交互

    前言作为小白的我,才开始入门IOS,选择了swift来进行入门学习,学习做着公司一个简单的小小项目,该项目需要进行跟H5进行交互,然后我就开始研究了UIWebView的使用,其实基本原理跟Android的一样,因为我是Android开发的,所以就顺水推舟了。))//这里设置你需要加载的地址}overridefuncdidReceiveMemoryWarning(){super.didReceiveMemoryWarning()//disposeofanyresourcesthatcanberecreate

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部