我们应该如何编写高质量的前端代码

编写高质量代码是每一个程序员必备的技能之一,可以有效地进行项目的维护以及项目的合作开发

01 前言


这要从很久的事情开始说起,前端最初的发展就像一团浑浊的云团,什么都往一块写,然后东拼西凑,最后竟然能运行。其实每个人前端人都会对页面的混杂感到头疼,谁不想好好优化一下呢?但是奈何那会没有成型的工具,更没有现在高质量的组件库,从此解放了我们的代码编写,真正做到了开箱即用,它不香吗?

从最初发展到现在,代码无非就是进行了高度的解耦,让每一个部分都负责自己的内容,把结构、样式与行为分离,使得代码的职能非常清晰,看什么都舒服。所以后来很多前端都要求把自家的网站进行重构,毕竟谁也不想接手上一代遗留下来的产品,自己重新写一套都比他们的要舒服。

02 代码维护难点


为什么说前端的代码难以维护呢?其实主要是出于以下的三点:

浏览器层面

浏览器是我们前端人经常打交道的工具,其实是浏览器孕育了前端这个大家庭,也是我们生存的根本。假如用户不需要看东西,不需要进行交互,或者我们就不需要存在了。不知道大家是否了解过全息投影?等到那项技术普及的时候,我们又是做着什么样的工作呢?

虽然现在浏览器的兼容性越来越好,主流的浏览器一般都会兼容很多css属性,最起码常用的、多人使用的你是一定要支持的,像flex布局这种神仙属性。当我们习惯于使用某一个浏览器(如谷歌)之后,再尝试使用360浏览器,你会发现自己根部看不下去。就像你习惯于使用谷歌搜索,但是要你使用百度一样的道理。

所以前端浏览器之间的兼容是我们必须要跨过的一道坎,即使现在的兼容性越来越好,但是用户群体也有很多使用IE或者360浏览器的,我们也不能忽略他们的使用。可是有一句话说,兼容IE就是浪费生命,自己细品一下。

技术层面

由于每一家的公司使用的技术都不太一样,事实上很多公司都会有自己内部的框架,我们要使用他们内部的框架与现有的技术框架结合在一起,那也是一件很头疼的事情。即使你是一位刚跳槽进来的员工,也是要学习他们内部的技术框架你才可以进行项目的开发。

很多公司创立阶段的时候可能vue、react等神仙框架还没出来,就是jQuery的天下,我们的项目底层也不是一朝一夕就能改变的,所以很多公司即使知道了新技术的出现,也不会去使用,也是处于探索阶段。假设公司需要使用一种新技术进行代码的重构,也可能因为员工对新技术的理解还不够深刻,写出的代码也会存在一定的设计漏洞。所以理解不深,就很容易写出难以维护的代码,给我们的团队造成阅读困难,最终也会变成一个难以维护的项目。

团队合作

团队合作才是真正的难题,不像我们自己编写的项目,想怎么写都行,不怕有看不懂的时候。当我们提交代码的时候也是不用经过其他成员的同意,直接push到master分支。这些都是我们个人开发的时候做法,到了公司层面或者项目的层面,那你就直接收拾东西吧。

大型的项目一般开发人员是比较多的,每一个人都会负责不同的模块和不同的功能,每一个人都会有自己独立的分支,代码合并到主分支的时候还得经过审核,这是一个完善、系统的开发流程。所以项目越复杂,团队合作的要求就会越高。一般我们都会有一种代码开发规则,大家都应该相互遵守,不然我们就会污染正常的代码,导致项目难以维护。所谓团队合作的最大困难不是技术,是人。

小结:

除了我们要项目的代码进行解耦,把结构、样式与行为进行分离之外,我们还应该重视简洁、可复用以及结构化的特点。当你能够做到这些的时候,你的项目就会显得专业,代码的可维护性以及可扩展性就会越高,开发人员添加新的功能或者模块就会显得比较轻松。

03 高质量结构代码


语义化

HTML5出来之后,添加了很多新的标签和属性,而语义化这个概念就出现在前端人的眼中。之前我们编写结构代码的时候一般会选择使用div与类名/ID名的方式来命名一个模块,所谓DIV+CSS开发模式就是这样由来。那么这种方式可否可行呢?当然是可行的,而且别人用的很舒服,就是cv操作多了点。

当然缺点是有的,比如最主要的就是结构不清晰,无论是编写导航还是模块、亦或是底部,全程div。这样结构就不清晰了,如果没有加以类名或者ID名,根本不知道你写的代码是属于哪一个模块。而且还有一点就是对搜索引擎不友好,不能准确识别你的网站结构和信息。

那么如何看你的代码是否语义化呢?很简单,把所有的样式都去掉,看你的页面结构是否显示正常,一般语义化的标签都会有默认的样式。如果显示还可以,结构有序就是语义化比较好了,反之你就重新写一下吧。

模块化

模块化其实就是跟在语义化之后的,如果你的语义化做的比较好,那么相应的模块化就比较好了。我认为模块化的重点应该关注你的标签选择是否合理,比如文字就使用p/span标签,标题应该使用H1-6标签等。不能所有的文字都是用div这个万能的标签元素,能用p的就不要去用div,因为p本身是针对文字的,有一定的基础样式。

小结:

不过现在我们似乎不会关注这些东西了,因为有了高颜值组件库的出现,需要什么直接cv过来使用。但是我们注意的是,并不是说这样你就逃避学习的理由,因为无论是多高大上的组件都是由最基本的样式和结构组成的,学会背后的造轮子思想才是最重要的。当组件不能满足业务上的需求的时候,就需要你进行css代码的编写了。

04 高质量样式代码


盒子模型

一般面试或多或少都会问一下你关于css盒子模型的理解,如果没有准备的小伙伴可能会把内容搞混了。这里再重复一遍:

  • IE:元素的宽度由width+border+padding组成
  • 标准:元素的宽度就是width,本身包括了padding+border
样式组织

关于我们页面的样式如何编写,也是我们要考虑的一个问题,我们关于样式的编写没有对错只有好坏。页面写出来,能够满足自己的期望那就是对的样式,是否合理又是另一方面的事情了。

所以这里可以参考一下样式的结构组织:reset.css+common.css+view.css

首先第一个是基本的样式标准,专注于底层的样式。这里的reset是指我们把浏览器默认的基本样式都重置一下,尽量满足所有的浏览器样式看起来是一致的。还记得我们之前说过通配符*吗?那是一个及其暴力的样式重置,但也是很危险的一个操作符。危险是因为需要遍历页面所有的元素节点,给他加上样式。这里我们就推荐使用网上的reset.css即可,都有很多供你选择,假如你懒得找且项目支持npm安装,直接npm i reset-css即可,简单快速方便。

common.css是指一些组件相关的样式,比如我们们如果在vue里面写代码的话就知道一个vue文件可以由三部分组成,其中一个部分就是可以让你编写属于组件的样式代码,这里我们重用组件的时候就会显得非常方便。关于view.css其实就是一个更高层次的编写,属于一个页面的样式文件。

选择器使用

选择器可对某一个节点进行样式编写,有同学可能会说,我能把我的节点样式应用成功就好,还需要关心它怎么使用吗?其实要的,我们先从css选择器的匹配方案说起,选择器是从右向左进行匹配的,.class ul li a p这样的选择器,会先从全局匹配p标签然后再匹配a标签,依次类推。

所以第一个问题就是我们一定要避免选择器的嵌套过深,因为很耗费性能。假如可以使用ID匹配到唯一的元素就不用使用其他的选择器了。也正是因为选择器的这种匹配规则,使得元素更高效的匹配,也是经过长期的验证得来的结论。最后我们应该更加注意样式的继承,避免多次编写重复样式,所谓少用组合,多用继承原则。

近年来出现的css预处理器可以有效地提高样式的编写,使用一种面向对象的写法,更大程度对样式代码进行复用,有stylus、scss、less等,读者可以自行去官网了解。

编码风格

样式风格:关于css的编码风格也是因人而异,一般来说我们应该使用多行的写法,因为这样可读性就更高。假如样式代码写在一行,难免造成阅读困难的情况。后期我们进行项目发布的时候可以进行对代码的压缩。

id/class:id选择器一般使用在全局唯一的元素节点上面,如果确定元素节点唯一的情况下我们就可以使用,但是假如元素节点不唯一,那么就推荐使用class。

05 高质量的行为代码


良好习惯

因为项目涉及到多人开发,每个人自己使用的变量应该自己来维护,这样可以有效避免代码冲突,覆盖正常的代码等。所以我们应该禁止直接在全局的作用域下进行代码的编写,这样很容易对别人的项目模块造成影响。那么我们的避免的方法有哪些呢?

  • 团队合作避免冲突

我们把自己的代码写在一个匿名函数里面,如(function(){})(),这样代码里面的变量就不会是全局的了,而是属于这个函数的内部变量,不会对他人的代码造成影响。用匿名的方式把代码包裹起来,可以有效控制全局变量,避免冲突隐患。

  • 统一入口

我们还可以给函数一个统一的入口加载文件,可以选择函数入口为init,这样所有初始化的操作都会在这里进行。通过这样我们就可以模拟DOMReady的事件了。

  • CSS放在头部,JS放在底部

这个操作应该是每个人都应该遵循的做法,这样更有利于浏览器页面的加载优化,减少页面空白的时间,提升用户体验。

JS分层

其实这里的分层和css的分层道理是一样的,也可以参考base层、common层、以及view层的形式。其中base层可以封装不同浏览器的差异,提供统一的接口,完成一些兼容的工作。common层提供可复用的组件,功能是给view层提供组件。common层和base层都可以为view层提供组件,不同的是common层可以提供更庞大的组件。比如一些拖拽功能的实现等。关于view层就是直接对前两层的调用,这里是关于页面逻辑的实现部分,如进行接口的请求等与具体功能需求相关的操作。

实用技巧
  • 弹性

弹性是指我们能够轻松应对客户提出来的需求,不用每添加一个需求就修改一些js代码,这是很不方便的事情。比如像事件代理一样,可以实现一些精简的操作,不用每添加一个节点就手动添加事件的监听函数。

  • 可复用性

现在基本上我们实现什么的功能都要先考虑一下如何才可以把这写代码进行复用,以减少一些业务相关或功能相关的代码,做到一次编写,到处可用。能够公用且不影响组件之间的功能就是我们的追求。实现的方法我们可以通过传参的形式来进行。

  • 避免副作用

我们开发的基础代码可能能够满足我们目前的需求,但也可能我们在使用的过程当中产生了一些副作用不是我们想要的,为了避免这个问题,我们应该考虑一下是否我们的函数耦合性太高,考虑解耦等。

06 小结


今天就和大家聊一下关于编写高质量的代码的事情,其实还有很多方面来不及编写,读者自己也可以自行查阅相关资料。主要是从结构、样式以及行为三个方面来进行讲解,这也是对应着我们前端的基本语言html,css以及js。

结构方面我们说了语义化编写和模块化编写,样式方面我们说了盒子模型,样式的编写、样式风格和选择器的使用等,行为方面我们说了关于编写的良好习惯,js分层等。

其实具体的实现还得大家自己进行感悟,这些都是前人总结下来的经验而已,项目之中的具体细节可以依据以上的规则来进行编写,相信应该会提升一个代码质量层级。