基于AngularJS的前端架构(上)
模块化
怎么分模块
AngularJS自己有模块的概念,但只是为controller、direcitive、service等提供一个集合的概念,并没有文件调度的功能。
官方推荐的模块分类方法是:
angular.module('app',['app.direcitve','app.controller','app.service'])
简单应用的话,这样分很方便。但是当controller、direcitive等都多了,并且互相有关联的时候(比如某个direcitive需要自己的controller),这样的分法就显得脏了。
改良方案很简单:将相关的directive、controller、service拆到一个同子文件夹中,形成以业务逻辑为关联的模块。如:angular.module('app',['app.user','app.message']
怎么处理第三方模块
AngularJS的第三方模块都会有自己的模块名,如表格控件ngGrid就占用了ngGrid
。这些模块名可能不符合我们的命名规则,但我的建议是不要去改动,免得升级什么的时候出问题。
angular.module('app',['app.user','app.message','ngGrid']
而应该在直接需要这个第三方模块的模块里去写:
angular.module('app.user',['ngGrid'])
原因很简单,几乎所有的第三方模块都是不涉及到系统的业务逻辑的,当你把第三方模块和某一个业务逻辑模块混在一起的时候,其他模块也需要这个第三方模块时,你会很容易就去通过依赖这个混合的业务模块来获取第三方模块。或者说你的同事很可能会这么做。
目录结构
说道第三方模块就不得不说目录划分了。 大部分时候我们的目录结构是这样的:
--app |--javascript | |--*.js |--css | |--*.css |--lib | |--bootstrap
简单应用的话这样划分足够了。不过既然说到了模块化,你应该已经猜到我要说的结构了:
--app |--thirdParty | |--moduleA | | |--js | | |--css | | |--lib | | |--subModuleC | | | |--moduleB | |--system | |--moduleC
不要说蛋疼,不要说“这在页面上加载脚本的时候还得一个一个去找js和css的位置”。如果你用grunt之类的工具的话应该知道这根本不是问题。这样划分的好处在于,几乎任何一个文件夹都是一个完整的模块,你可以随便拷贝到任何地方去测试什么,或者在其他简单环境开发好了再丢到系统目录下。system
和thirdParty
这两个目录的划分是用来区分通用模块和业务逻辑模块的。其实这就是典型的服务器端框架目录划分。 不过实际应用中,这样目录结构还是有问题。特别是当你使用less的时候,如果你的less文件依赖thirdParty中的less库,那你在测试的时候就不得不保持住这个相同的目录结构。
CSS和HTML
less
这里只讲less的规划。
首先在大应用里我不推荐直接使用bootstrap。虽然很好用,但是应用复杂了之后,必然会存在大量自己的样式。这时候html上的class就会乱成糊了。建议页面上只使用自己的class名,并且最好是有逻辑意义的。bootstrap可以作为底层。这里值得一说的是命名规则。既然已经有了less,页面上就不再需要通过组合方式来控制元素的样式了,如果有class组合的话,应该都是有语言的。打个比方,以前的写法:<div class="alert red">you are on fire.</div>
现在的写法:
<div class="message danger">you are on fire.</div>
less文件:
.message{.alert;} .danger{.red;}
怎么来区分模块和通用样式?很简单。每个模块占用同名的class名,首字母大写。当然你可以用其他的方式。在我的系统中,对通用class(如danger)添加具体样式是严格控制的。这样就能让样式的来源变得单一,当发现问题时,我马上就能知道到哪里去改。实例:
<div class="User"> <div class="User-name">Jason<div> <div class="User-signature important">Hahaha.</div> </div>