曾有人调侃,设计模式是工程师用于跟别人显摆的,显得高大上;也曾有人这么说,不是设计模式没用,是你尚未到能懂它,会用它的时候。css
先来看一下比较官方的解释:“设计模式(Design pattern)是一套被反复使用、多数人知晓的、通过分类的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构同样。”html
今天咱们来聊聊CSS的设计模式。前端
设计模式,这个词汇咱们常见,几乎全部的编程语言都会有几套,但深刻研究的人很少,缘由以下:编程
一、彷佛没有太大必要性去强调它,有问题了改一下或者按团队规范来就行;设计模式
二、不去使用一些既有的模式也无伤大雅;浏览器
三、很多人所接触的业务量级尚未达到须要规划和组织的程度,光写布局,写特效,照顾兼容,就够喝一壶的了,没有意识去思考一些方法论的问题。编程语言
固然,这三者都是我经历过的,相信你也是~组件化
咱们都会长大,都会慢慢的作更多、更大、更复杂的项目,这个时候,就须要自上而下,全流程的去思考一些问题。后台不说,只讲前端,好比:风格的制定、色调、模块、布局方式、交互方式、逻辑等等,若是再加上团队合做,若再没有一个规划的话,要不了多久,那些看起来没问题的代码,就会暴露出各类问题,模块命名、类的命名、文件的组织、共用模块的提取、代码的复用、可读性、扩展性、维护性。它们看起来只是一些简单的小动做,却须要你看得更远,避免未来出问题须要付出更大的代价,甚至被迫整个项目重构,可谓,功在当代,利在千秋~布局
既然要对CSS进行设计,那么确定是它自己存在一些问题或者缺陷,其中,一个最明显的就是,它的任何一个规则,都是全局性的声明,会对引入它的页面当中全部相关元素起做用,无论那是否是你想要的。而独立及可组合的模块是一个可维护系统的关键所在。下面,咱们就从多个层面来探讨一下,到底该怎样写CSS,才是更科学的。学习
分
咱们刚开始学习写字的时候,是不会去考虑,写出来的某句话好很差,文章结构合适不合适,由于咱们是意识不到的。写代码也同样,刚开始,咱们只是去定义规则,能用对了属性,语法正确,把页面实现出来了,就好。慢慢地,就会发现,页面也是有结构的,咱们按照页面的结构去组织代码,会不会更好?好比,分红头部、导航、侧边栏、banner区、主内容区、底部等。
然而这样貌似仍是不够,由于还有一些东西,复用度是很高的,又很差把它归为任何一个固有模块,好比:面包屑、分页、弹窗等,它们不适合被放到某一个固有模块的代码中,就能够单独的分出一段专属的css和js,或许,这就是组件化的由来~
拆
在分了以后,咱们的代码看起来已经比以前好不少了,组织清晰,维护性大幅提升,可是,好像仍是不够,咱们会发现另一些东西,很细小,但复用度也很高,它们一样不适合被放到模块中去,好比,边框、背景、图标、字体、边距、布局方式等等。若是咱们在每一个须要它们的地方,都定义一次,它们会被重复不少次,显然,这背离好的实践,会形成代码冗余和维护困难。因此,咱们须要“拆”。拆过以后会怎样?咱们想在哪里用能够直接加,须要改的时候统一改。
排
通过了“分”、“拆”,咱们的代码结构已经十分清晰,各个内容模块,功能模块,UI模块都乖巧的等待召唤,那么还差什么?是的,还差有序的组织,分类清晰以后,还须要排列有序,从不一样纬度去考量,咱们总能精益求精。举个栗子,咱们可能会看到像这样:
@import "mod_reset.css"; @import "ico_sprite.css"; @import "mod_btns.css"; @import "header.css"; @import "mod_tab.css"; @import "footer.css";
咱们将不一样的部分按照必定的顺序去摆放,能让咱们的代码看起来更加有序,易于维护,同时,有利于进行继承或层叠覆盖。不要小看这一步,看似无关紧要,实际要求比较高的统筹规划能力,能够减小冗余代码和快速定位问题位置等。
除此以外,咱们依然能够有其余的方法来帮助咱们进行区分代码范围,好比:
一、在文件头部创建一个简要的目录
二、使用区块注释
在注释中,应该尽可能详细的写清楚该段代码的目的,状态切换,调整缘由,交互逻辑等等,这样不只利于本身的维护,更加利于别人接手维护你的代码。
除了需求当中一些通用部分,另一些也是须要注意,但不会被正式定义的东西,它们来源于咱们的实践经验,好比:
层级嵌套不要太深
稍微了解一些浏览器渲染原理的都知道,它在解析CSS规则的时候,是从右向左,一层层的去遍历寻找,若是层级太多,必然增长了渲染时间,影响渲染速度。另外,若是选择器层级过多,也就间接反应了,你的HTML结构可能写得不够简洁。
那么具体多少层合适?通常建议是不超过4层,但话又说回来,超过4层会怎样吗?不会有多明显的影响,除非你写到很恐怖的数量,或者项目极其庞杂,可能能看出来影响,其实从咱们平常需求来看,4层之内足能够解决绝大多数问题,故而,是合理的。
避免使用元素选择器
出于两点考虑:
第一点,和上一段提到的相关,在HTML中,有不少经常使用的高频元素,好比,div、p、span、a、ul等。若是,你在多层选择器的最内层使用了元素选择器,那么,在开始寻找时,浏览器就会遍历HTML中的全部该元素,显然,这是没有必要的。
第二点,咱们的需求和代码结构都是存在着潜在变化的,今天写好了一个页面,明天可能就要再加进去一个按钮,再加进去一句话,再加进去一个图标。咱们写好的一个结构,也随时可能被复用到别的结构中去。因此,若是,你使用了元素选择器去定死某个东西,不管是新加进来的东西,仍是被复用的东西加到别的结构里去,都极有可能产生样式的冲突,这个时候,你又不得不写多余的样式进行覆盖修正,或者从新定义类。
因此,出于以上考虑,在具体的代码模块中,尽可能不要使用元素选择器,使用元素选择器的前提是,你彻底的肯定,不会致使出现问题。注意,我用的限定范围是“具体的代码模块”,那么用于定义通用规则的样式,是能够的,也是推荐使用的,好比,reset。也能够是别的地方,这就须要咱们自行考量。
避免使用群组选择器
群组选择器会有什么问题?直接上图吧。
图中这种状况很少见,此处只是举个例子,这里写了三组选择器,用来定义不一样地方的同一种样式,其明显的缺陷是,若是有第四个地方须要使用到,你不得再也不往里加一组选择器,若是有10个不一样的地方,你就写10个?这对于维护来讲,是很痛苦的,聪明的咱们,怎能被如此繁复又没必要要的劳动所困扰,故而,墙裂不推荐此种作法,彻底能够提取出来一个公用类,定义统同样式,而后,哪里须要放哪里,复用和维护都会更加方便。
固然,你可能会说,我在写第一个的时候,不会知道后面还有那么多,有没有必要提取是不知道的,是的,因此,须要你根据经验去判断,也须要在项目推动过程当中,适时的对代码进行整理和重构。
文件引入的数量和顺序
对于刚接触网页的朋友来讲,这两点也是容易忽视的,由于它们看起来没什么大影响,多几回请求,样式是否已经加载,都没那么容易把人逼疯。可是出于对用户体验的极致追求,咱们仍是但愿文件请求次数尽可能少,内容的显示有个优先顺序,文件加载有个前后顺序。这样,在实在难以缩减文件大小的时候,让用户先看到更重要的,正常展现的内容。
以上只是几点举例,更多实战结论,你们能够多读相关的博文或者书籍,都会有前辈们的经验之谈。
通用和语义
Naming convention is beneficial for immediately understanding which category a particular style belongs to and its role within the overall scope of the page. On large projects, it is more likely to have styles broken up across multiple files. In these cases, naming convention also makes it easier to find which file a style belongs to.
命名规则有助于当即理解一个特定样式属于哪一类,它在页面的总体范围内的做用。在大型项目中,它更可能有在多个文件中被打破的样式。在这种状况下,命名约定也能够更容易地找到一个样式属于哪一个文件的文件。
不少时候,咱们须要一个东西被定义为通用的,以便复用,好比:模块标题、按钮、提示文字、图标等,最开始的时候,咱们习惯去看视觉稿的内容,是“新闻”,咱们就定义“news”,是“关于”,咱们就定义“about”,是红色的按钮,咱们就定义“red-btn”等,这样会致使一个问题,若是有另一个跟新闻列表差很少的样式和结构,但不是新闻,怎么办?继续使用“news”显然不合适,这就告诉咱们,不能把目光局限于内容,须要内容和结构分离。
不能用“news”了,那用什么呢?abc?123?这样总不会冲突了吧,万事大吉~其实,这是走了另外一个极端,这样虽然在很大程度上避免了和别的模块冲突,但其自己的可读性就被大大下降了,别人,甚至你本身过一段时间都会忘记它是什么,对于团队合做是很不利的。至于须要用什么样的命名方式,须要你根据项目的总体来进行规划,适合根据什么特色来区分与之不一样的结构,又能让人比较容易的在名称和结构之间创建联系,好比所属类别、功能、页面等。
团队和我的
一个团队当中,你们的经历不一样,编码水平和习惯也不一样,这样就会形成,一我的一个写法,你用中划线,我用下划线;我用英文全拼,你用简写,等等。这些虽然没有什么对错之分,但对于团队成员之间的协做形成了不小的障碍,别人必须花时间去适应和读懂你是怎样组织和定义的,这就无形之中提升了成本。
因此,就有了“团队规范”存在的必要,规范除了一些写法上的规定,让咱们的代码更加统1、清晰、可读性更强、辨识度更高。还能够提取一些最佳实践和复用模块等,对于团队里每一个人来讲,都是有好处的。
固然,对于人来讲,最难的,莫过于调整既有的习惯,这就会有进入一个团队以后“转型”的阵痛,其实这种痛也是成长的痛,你会学习到更好的编码方式,更好的实践方法,会从项目或者团队的总体去考量一件事的价值和意义。
CSS和预处理器
前面我有文章详细的谈过CSS预处理器,我曾经对它也是排斥的,由于学习成本,由于以为应用起来没有必要。但是一旦你决定去学习使用它,就会以为不是那样,预处理器在向你介绍它本身的时候,就有特地强调过,它的语法是和CSS彻底兼容的,也就是说,你在LESS或者SASS文件中,直接写CSS代码是没有问题的。除此以外,它能给咱们提供不少便利,好比定义统一的变量;使用嵌套而不用一直重复着写一些选择器;能够提取公共的代码块而后很方便的复用等等。
故而,当咱们已经把CSS组织和书写得很好了以后,预处理器,就是再次为咱们插上一双翅膀,能更灵活和高效的编码。
再来简单看看一些广为流传的模式。(ps:前后顺序与排名、好坏无关)
1、OOCSS——Object Oriented CSS
接触过计算机的应该都知道,OOP——Object Oriented Programming,若是你是第一次接触OOCSS,你会很困惑,难道是“面向对象的CSS”吗?它不是一本真正的编程语言啊,如何面向对象?
OOCSS,最先被说起,是在2009年,它的两大原则是:
separating structure from skin and container from content.
直译过来就是,结构和皮肤分离,容器和内容分离。
即不要把结构和皮肤以及内容进行强耦合,而是相互独立,所要达到的目标是更易复用和组合,能够选择使用,选择引用等。
详细了解连接:https://www.smashingmagazine.com/2011/12/an-introduction-to-object-oriented-css-oocss/
2、SMACSS——Scalable and Modular Architecture for CSS
从实践上说,OOCSS给出了一种值得借鉴的思想,但在代码的组织方面,它并未给出具体的实施方法,从这一点上来讲,SMACSS更进一步。
它的核心是:
一、Base(基础)
基础的样式,就是一些须要最早定义好,针对于某一类元素的通用固定样式。
二、Layout(布局)
布局样式,是跟页面总体结构相关,譬如,列表,主内容,侧边栏的位置、宽高、布局方式等。
三、Module(模块)
模块样式,就是咱们在对页面进行拆的过程当中,所抽取分类的模块,这类的样式分别写到一块儿。
四、State(状态)
页面中的某些元素会须要响应不一样的状态,好比,可用、不可用、已用、过时、警告等等。将这类样式能够组织到一块儿。
五、Theme(主题)
主题是指版面整个的颜色、风格之类,通常网站不会有频繁的较大的改动,给咱们印象比较深的是QQ空间,其余应用的不是不少,因此,这个通常不会用到,但有这样一个意识是好的,须要用到的时候,就知道该怎样规划。
有了以上5点分类策略,咱们的代码组织起来,思路就会很清晰,会安排的颇有序,另外的好处是,能够解决命名难和混乱,之因此有这个问题,主因即是咱们不知道以怎样的标准去定义元素的所属和特色,有了分类以后,咱们不会很随意和混乱的去命名,有了依据,就能更轻松,也不易冲突。
详细了解连接:https://smacss.com/
3、Meta CSS
原子类,也能够称之为“无语义”类,像这样:
它的特色是什么?样式和结构、内容无关,预先定义好这么一组规则,在须要的地方加上便可,我相信每一个人第一次看到这种写法的时候,都会想:还能这样写啊?!是的,总有一些人,一些新的思想和方法会涌现出来,它就是其中之一,固然,并非在称赞其自己有多么好,而是说这种现象和过程是好的,它自己常常被人吐槽,好比:“这样写和直接内联有区别吗?”、“若是要调整样式,就要去改HTML,维护更加麻烦,也有违样式和结构分离的初衷”等等,其实我我的也是不同意上面这种写法的,若是你要把这些抽离出来,那么还有什么抽不出来的呢?并且这些属性,在项目之间,页面之间,模块之间,并无太大的通用性,把这些抽出来,只不过是稍微懒省劲儿些,但为了照顾到更多状况,你必须写入冗余代码,是得不偿失的。
虽然它有缺点,我我的同意另外的一些东西分出来,好比:浮动(float)、文本布局(text-align)、Flexbox布局等,这些是没有那么多可能性的值,并且使用频繁,复用方便,改动较少,除此以外,你还能够提取另一些公共的小颗粒类,好比按钮的种类,文字颜色的种类等,这些和CSS自己无关,和项目相关,这就是借鉴其思想,而不是直接拿来用。
4、BEM
严格说来,BEM不是一套有骨有肉的模式,也不只仅局限你在CSS的层面去规划,它是一种怎样去组织、编写代码的思想,并且,看似简单的它,对前端界的影响倒是巨大的。
它的核心以下:
Block(块)、Element(元素)、Modifier(修饰符)
它帮助咱们定义页面中每一部分的级别属性,从某种意义上说,也是一种“拆”。命名规则以下:
它的出现,曾给很多人带来启发,可是也有另外一部分人仍然抱着挑剔的态度,譬如:
一、风格不统一,显得代码不够整洁美观
二、可能会致使类名过长
仍是前面说的,你能够不去直接用它,但要清楚它的优势:可以使得咱们仅经过类名就知道哪些代码是属于一个模块内,以及在模块中所起的做用。而后借鉴之。
固然,BEM集聚了不少人的心血,也获得了不少的赞誉,其中就包括OOCSS的做者。因此,它确定不是这么简单。它还会告诉你,怎样配合着js来写,你的文件怎样组织更好,项目该怎么构建等。详细能够到官网去查阅。地址:https://en.bem.info/
到底怎样使用设计模式?
虽然已经有成熟的设计模式,但在实际当中,你可能以为哪一个跟本身的项目都不能彻底吻合,或者你要去为了使用它们而调整,成本很高。其实,咱们不须要去迎合模式,要让模式为我所用,你须要去了解它们背后的原理,要知道它们用什么方式解决了什么问题,而后借鉴之,用它的方式解决咱们的问题,就好,这样就不须要做难要不要用,也不须要纠结选哪一个,不是简单的说哪一个好,哪一个很差,总有咱们可以用得上它的地方。海纳百川,集百家众长。
我我的一直以来所坚持的另外一个观点就是,前端开发的三驾马车——html、css、js,不要,也不能孤立的去谈那样好或者这样好,咱们极少会有只用一次的代码或者模块,也不会只写一种语言,三驾马车都是在一块儿协做的,都是会有复用、扩展和团队合做多方面的因素在里面。故而,不能抱着这样的想法:我如今就在作这个,它就是惟一的,就是固定的,没问题。其实不少问题都是潜在的,要带着发展眼光去看待。项目的文件之间,项目之间,团队成员之间,不论你的分工是哪块,都要考虑到先后的影响和可能给合做带来的不便。
怎样才是最佳实践?有“实践”,才有“最佳”,脱离实际状况谈最佳,就是空中楼阁。那么,最好的模式,不是哪一个经典的模式,而是在项目进行中,不断的磨合调整而出的。故而,不须要再害怕看起来不明觉厉的设计模式,也不须要由于本身还不懂设计模式而郁闷,它就是人们总结出来的实战方法,你也能够有本身的模式~