最近半忙不忙的写了一个外包网站,网站主要功能是艺术品竞拍和艺术衍生品的销售。工程已经完成了80%左右,现在前后端代码量已经50W行左右,我主要负责的是前端设计和前端布局。下面就先放一个网站的设计图吧,因为涉及到甲方的“商业机密”,所以打一下马赛克:
这篇文章主要算是我对于这个项目的总结或者说是对于这阶段自己看的一些前端书或者经验的一个总结吧,所以设计图就不贴那么多了。整个项目的设计图由最开始的ui定了个首页稿基调,剩下的界面大部分都是我在首页稿基础上做出来的,以后有机会再唠。PS:不过话说博客园里现在遍园子都是.net的文章,前端的文章除了js的,就是那些“可复制可粘贴”的源码文,希望以后能看到更多前端好文吧。
整个网站的单界面(不包括后端)已经有3,40个了,css文件累积下来也有10多个(这个之后会细说,这块儿是我这个项目中做的最失败的一部分,也是我写这个blog的原因)。
一个一个问题的唠,我就说说自己的理解,不太对的地方欢迎交流:
一、什么是css的架构?为什么要做架构?
如果做的是一个小的博客网站或者说是一个小的CMS,那可能很多时候不用考虑css的架构,因为css文件很少,总共就不到10个界面,给每个界面单独写样式、单独封一个css文件也没有太大的工程量。但是,如果换到这种界面数达到几十个或者几百个的大型网站中,css的架构就非常有必要了。而且,好的架构能够帮助团队共同开发,不可能说总共几十个界面,3个前端,一人分十几个,好,你们去写吧,这样的工作效率太低,而且极易导致样式冲突和样式被覆盖,可能写起来很快,每个人都很勤劳的把自己的代码写完了,然后后端总合之后发现样式全乱了,一改改了好几天,比写都慢。
合适的css结构能够帮助开发者减少代码量,能够帮助前端开发团队在共同开发的过程中能够更好的合作。同时它也能优化前端的整体结构,合理的css架构能够减少css文件数目和css文件总大小,降低对服务器的访问压力。
它也能大幅度提高前端代码的重用度和减少代码的维护成本。对于那种1个小时想改一次界面的甲方,没有好的css架构真是要疯了。比如说你每个页面都有个标题栏,每个页面都是一个单独的css,然后突然有一天甲方深井冰一样说,我想改一下样式,这时候你只有两个办法:1.抱着甲方大腿哭诉求不改2.默默打开电脑开始一个界面一个界面的改。看到这里很多有开发经验的同志们应该都知道说,提取这个标题版块,写在统一的css文件内,每个界面都引用一下,最后想改的话只要去总的那个css文件里面改就可以了。这就是最简单的模块化,不过,模块化的过程中还有很多问题需要注意:1.比如3个界面都有标题栏,但是3个界面对于标题栏字体颜色的要求各不相同怎么办?对于上下margin的要求又不相同怎么办?2.突然多了一个界面,它有标题栏,但是它标题栏里多了个背景图片,这个怎么解决?再麻烦一点,它标题栏里多了一个<p>表签,多出来的又怎么布局?这种解决模块之间差异的问题确实值得好好研究一下。
通常的css架构,或者是当前网站的css框架,包括了对浏览器默认样式的覆盖重置、对网站内部模块的提取抽象化、约定css代码规范、冲突解决等功能。如果项目中有引用其他的成熟框架,比如说bootstrap、yui,怎么把这些框架和自己写的分割开,能实现样式而又不冲突?稍后慢慢唠。
怎么做css架构或者怎么实现简单的css结构?
答:写代码啊!
二、css的架构从哪里做起呢?
动手一个项目前,不能看到设计图就直接干,应该先想的是怎么样去写。就像我们老师最常对我们说的一样“只会写代码,你只是平庸的程序员。能够做出好的架构或者能够安排好项目怎么开发的,才是高端点儿的程序员。平庸的程序员只能吃香蕉,高端的程序员有时候还能吃点菠萝、苹果啥的”。直接动手开始写,写着写着就会发现很多时候自己是在做重复功,不断地复制粘贴或者是为了一个界面模块重写一种又一种样式,或者写着写着发现“卧槽,冲突了,样式乱了”,再或者写着写着发现自己写的不对想回去改,然后开始挨个文件的改...这种没有架构的、笨拙的在写css就是在干体力活,很久之前写的一个项目就是这样,20几个界面慢慢改去吧,改了整整两天,都要疯了...
动手一个项目前,最起码的,应该想清楚大致有多少个css文件,哪些css文件需要先写出来一个固定版本,哪些css代码可能会大量重用,哪些css文件可能会有大规模的改动。然后根据这些css的详细要求去开始动手写初版。
比如我上面放的截图,最直观的header首部栏:,在每个界面都是一样的。当然这个我们可以在后端里面用分布视图layout来实现,但是在界面前端实现的初期,是不是也应该把这一块儿的html、css、js抽离出来,这样在后端进行最后整合的时候也能快一些,而且万一碰到个圣诞节,客户说给上面背景色换成蓝色吧,这样直接翻到header.css里改一改样式就好了,不用苦逼的去“体力活”了。
所以,第一种css前端架构设计的方式就是:按照区域划分。
按照页面内的元素或者模块的区域定位,网站中可以划分出来很多区域:header、footer、sidebar、slogan等等,针对于这些区域单独定位能够有效的实现分布视图的划分,每个区域都被抽离出来,新建一个界面的时候我们只需要在里面拼一拼就好了。没记错的话,yui就是这么干的。
在这个拍卖网站的css里我没有单独抽离出来,因为我觉得单独抽离成一个header.css、footer.css文件有点赘余,css文件数在增多,而每个文件内的代码行数却很少。这个还要根据具体代码来看,一个footer样式写了几十行的话,那就抽离成一个文件吧。所以我在总的css文件:layout.css里其实是按照区域进行写的:。当我想要更改底部导航样式的时候,直接就去layout.css里往下翻找,改掉就可以了。
然而我们对界面进行分割之后发现,还是有很多代码在大量重复出现,比如说登陆框、比如说表格、比如说文本框等等,所以有了第二种划分方式:按照功能进行划分。
按照功能划分就是看元素的界面内功能是什么,然后根据具体功能,把具有相同功能的元素、模块抽离出来:font、color、button、form等等,这个应该是现在很多成熟框架采用的模式,比如我大bootstrap就是这么干的,下面是bootstrap2.3的less文件夹的截图,很明显,都是一个个功能模块,最后我们直接应用的是被全部整合压缩的.min.css,里面其实也还是这种结构:
按照功能划分还是蛮爽的,因为你可以为每个功能划分添加统一的前缀,在有代码提示的编译器里写代码简直极速。换成那种按区域划分的话,有时候就略微蛋疼了“哎呀,页脚的css名是什么?哎呀,小王写的那块儿侧边栏的类名是什么”。
在这个项目的代码里,我其实采用的是第一种方式和第二种方式混用的模式,从我上一张css文件截图就能看出来,我不仅把重复出现的区域模块的代码抽象了出来,而且也把侧边栏、遮罩这种功能模块给抽象整理了出来,尽量提高我的代码的复用度。
之前还觉得自己的这个项目的架构做的不错,但是后来越写越坑,因为很多时候自己都是在做无用功。我犯的傻X错误:
1.模块抽象有局限。比如说表单有要差一个特殊的元素,原来写好的模块就没法用了,又得重头写一遍。
2.模块抽象不完全。在我认为自己已经把模块抽象做的差不多的时候就开始全力写,写着写着发现,有的模块被遗忘了,很多模块需要一遍一遍的手写。
3.css类名不规范说到底是模块没有划分好。这个网站写到现在,我的命名已经词穷了,它这里有很多界面:加入购物车、加入收藏列表、查看购物车、确认支付、填写确认订单、一口价支付...没有好的英文底子真是噩梦...所以只能翻译汉语名,然后驼峰命名法:AddCart。其实命名法还有很多,驼峰命名法最大的好处就是可以很直观的命名,不用考虑别的,但是驼峰命名法在子类命名的时候就比较头疼了,一个又一个的长单词...另一种命名方法是划线法,为了避免麻烦直接用的下划线没用中杠add_cart,这种命名法对于子类命名特别爽,这个后几篇总结的时候再唠。
------------下面---------就是------------本篇-------核心-----了---
下面就是本篇文章的【核心】了,也是我痛心疾首的反思T^T最近项目受阻、半写不写的状态,所以看了一些前端代码规范、网站前端开发的总结的书,然后发现了一种新的结构方法,看完之后真是整个人都不好了。推荐这本书《编写高质量代码-web前端开发修炼之道》
另一种比较推荐的css架构方法是:按照界面职能进行划分:这里将网站的整个前端抽象成了一个软件或者是一个项目,这时候我们要考虑的就是项目底层是什么,项目的表现层是什么,类似于大家常说的mvc的思想,把前端架构也进行mvc般的划分,可以把所有的css文件归纳为三类:
1.base类 2.common类 3.page类
这三类并不是像区域架构、功能架构中并列作用的模式,而是以base类为底层,逐层影响,层叠作用,大概画了个作用图:
确实,就像这种金字塔结构,下面详细介绍一下每个类的作用。
[1.base类]
顾名思义,基础,它是整个css架构中最基础的部分。它负责提供浏览器默认样式重置、基础功能实现。说到base里的基础功能实现,它主要指的是那种涉及范围极小、抽象程度高的原子级别的功能类实现。比如我们最常见的.f12{font-size:12px;},.mt30{margin-top:30px;},每一个原子类只负责实现一种功能,绝对不涉及到具体的页面ui,只是为上几层提供原子功能,具体某模块的实现则有这些原子类间进行组合实现。当然,base类还要负责浏览器默认样式的reset,这个我觉得yui实现的就很靠谱,现在很多网站的<h123456>都是不加粗的,这个都需要提前在reset部分写好。
base类是整个css架构的地基,所有界面都会引用整个文件,这对这个文件提出了要求:1.文件大小不能过大 2.文件可靠性要高,不能出现多个版本 3.写成之后尽量减少维护次数或者尽量不用维护。而且不同网站的base类可以共用,因为base类不涉及任何具体的ui样式,高度可移植。
具体base类文件都有什么,这个下一讲来好好唠唠,今天没空了。
[2.common类]
普通类,它是利用css基础类实现的基础模块的css文件,我们已经把整个界面里的文字、边距、颜色等原子工程抽离出来了,现在需要我们为当前网站定制模块了。
设计原则里“统一性原则”要求到同一网站必须保持风格一致,你不可能首页扁平化,进了列表页就来个高光高阴影还带酷炫flash的web2.0风格页。所以,同一网站内的搜索框、文本框、按钮、列表大多数情况下都是统一风格的,所以这就给我们个机会,把这些会重复出现的模块抽离到common类里,类似于MVC里面的model,也类似于我们上面讲述的架构功能划分的具体功能文件。为了尽量保证可重用和灵活使用,我们需要对这些模块进行完整封装。
话说,模块需要进行订制时怎么办?
我想到了两个办法,一种是利用less等语言给模块预留样式接口,直接修改配置文件,再动态输出css文件。2.尽量减少模块的ui属性,比如bgcolor或者是border,可以空缺,而在实际使用时根据自己的需要与原子类进行组合。但是这种方法可能会对原子类有要求而且会对base文件产生影响,所以我自己又编出了个词:分子类,显而易见就是提供针对于模块的大原子类定制,为每一个模块定制专属样式类,同样至于common层,需要定制模块样式时只需要彼此组合即可。之后的文章里写点东西示范一下。
[3.page类]
页面类,从图里也能看出来,它在金字塔的塔尖,而它的作用范围也是最小的,就是每一个页面,到不至于每一个页面一个css,但是也差不多吧。 page类就是负责提供页面级样式的。page类css可能产生一些比较令人纠结的问题:1.page太多,所以page css单文件太多,每一个文件就是一个http请求,服务器能受得了不?2.page css为了不多,所以合并在一个page.css里,但是命名怎么办?比如.part, .one, .main, .theme....这些频繁出现的类名合并冲突怎么办?
第二个问题可以通过命名范围限定来解决。
至于第一个问题,你可以把css单文件合并,然后你就去看第二个问题的答案吧。
总结下来,在开发中,base和common类一般由一个人完成,在他完成这些类之后其他人接手项目,开始添些page.css,所以page层里代码奇多,如果应用到分布视图,一个整页面其实是由若干个小界面拼起来的,那么如何避免冲突?如何避免样式覆盖?以后详谈。
_(:з」∠)_码了这么多字累死我了,今天就先写到这。下篇见~~【求交流求师傅带求内推求不吐槽...】
下一篇文章,咱们详细谈谈base类css文件,以及我自己对项目css的重构。
最后,最后,我想说的就是↓↓↓