如何将前端代码写的优雅?
前言
作为一个前端工程师,令我最头疼的两件事,一个是逻辑混乱且没有注释的js代码,还有一个就是污染严重、命名奇葩的css样式了。
在项目开发中,扎实的基础和高超的技术水平固然重要,但是良好的编码风格也是不可或缺的一部分。开发一个业务或许只需要几天或者几个月的的时间,但项目在线上运行和迭代可能有几年甚至十几年。高质量的代码不仅能提升自己的编码风格、方便错误检查,对后续迭代优化的作用是非常显著的。
如果不想让几个月后的自己看不懂自己的代码,或者不想让后续开发的小伙伴对着你的git提交记录捶胸顿足的话,请尽可能的提升自己的代码质量吧!
以下为文章目录结构:
- css篇
- 常用的样式命名英文缩写
- 定义一套合理的规范
- css编译器
- 你不知道的css编写小窍门
- JS篇
- 注释注释写注释
- 不要写魔鬼数字
- 嵌套不要过深
- 合理抽取组件及函数
- 注意边界条件
CSS篇
关于CSS,基础很重要,不论是css标签权重还是布局原理,都需要有所了解。这里建议去官网学习CSS及CSS3的各种基础属性,并推荐一本讲述css原理的书籍----张鑫旭《CSS世界》。
对于写出优雅的css,我有以下几点总结:
- 擅用英文缩写
- 合理的css编写规范:bem命名、属性顺序
- 不要滥用id选择器和 !important
- 按需使用less等预编译器
- 合理合并与拆分
详细的描述见下文:
常用的样式命名英文缩写
一个项目通常有很多个小伙伴开发过,虽然现在基本上没什么前端开发人员用
class="zuobian"
这种中文命名了,但是当看到错误的英文Class,如class="head-titel"
(title) 和超长的命名,如class="page-Special-populationl--background"
,也是很让人抓马的
对于class命名,我们需要知道一些基础的规范和缩写。其他需要根据业务代码命名的情况,用即再查即可,对于非约定俗成的缩写,我们遵循的原则是:尽量不缩写,保证可读性。
以下罗列出最最常用的一些缩写
语义 | 缩写 | 全称 | 语义 | 缩写 | 全称 | |
---|---|---|---|---|---|---|
头部 | hd | head | 主体 | main | main | |
侧边栏 | sidebar | sidebar | 底部 | ft | foot | |
导航 | nav | navigation | 选项 | tab | tab | |
广告 | ad | advertise | 激活 | active | active | |
显示 | show | show | 隐藏 | hide | hidden | |
禁用 | disabled | disabled | 扩展 | extend | extend |
以下为常用的一些英文单词,通常会结合使用,如侧边栏的头部名称: sidebar--title
语义 | 编写 | 语义 | 编写 | |
---|---|---|---|---|
标题 | title | 列表 | list | |
内容 | content | 标识 | logo | |
搜索 | search | 提示 | tips tips | |
版权 | copyright | 输入 | input | |
结果 | result | 下载 | download |
更多关于css命名相关的缩写可见:CSS规范命名
定义一套合理的规范
通常一些中大型的公司,或者成熟的前端团队,会对css代码编写有一套自己团队的简单规范。规范不必过于苛刻,目的在于提升开发效率、降低维护成本。
在业界之前比较流行的css编写规范是BEM规范【块(block)、元素(element)、修饰符(modifier)】,实际也可根据团队情况制定推动更符合业务场景需要的自己的规范。
例文:这里推荐几篇篇详述CSS命名规范的优质文章:
- CSS-BEM命名规范
- 18种推荐的CSS书写规范
- css样式简写
以下以BEM规范为主,加上了一些自己对css规范的理解:
1、bem命名简述
示例:
<div class="health-account"><div class="health-account__head"></div><div class="health-account__body"><div class="tag"></div><button class="health-account__button--primary"></button><button class="health-account__button--success"></button></div>
</div>
总的来说有以下三点核心:
- -中划线 :仅作为连字符,表示某个块或者某个子元素的多单词之间的连接记号,如health-account。
- __ 双下划线:用来连接块和块的子元素
- – 双中划线:用来描述一个块或者块的子元素的一种状态
Tips:
- 并不是所有地方都应该使用BEM命名方式,如果只是公共的单独样式,就没有使用BEM的意义。BEM的初衷是为了明确模块的关联关系,提升语义化,同时也避免css嵌套过深。更多的细节这里不再赘述,可查阅相关文章。
- 避免过长的样式名称定义,如 .block__el1__el2——selected
- BEM命名方式势必会比普通定义的命名要长,势必会降低代码整体的可读性,尤其在less这样的预编译工具(后面会介绍)出现后。但这种命名规范在局部关联关系强的模块中还是很有必要的,对样式丰富的组件,这种命名方式也可以在CSS代码中避开过深的层级嵌套,提升性能,因此BEM规范可在项目中灵活使用。
2、合理的属性书写顺序
不管是直接书写css,还是使用预编译的工具,都不可避免的要书写css属性。对简单的样式来说,属性的简写和书写顺序未必显得重要,但在复杂页面上,合理的顺序对于快速定位样式问题是非常有帮助的。
建议按照布局定位、自身属性、文本属性、其他属性的顺序来书写,而不是想到什么写什么:
- 布局定位属性:position display float left top right bottom overflow clear z-index
- 自身属性:width height padding border margin background
- 文字样式 font-family font-size font-style font-weight font-varient color
- 文本属性:text-align vertical-align text-wrap text-transform text-indent text-decoration letter-spacing word-spacing white-space text-overflow
- 其他属性(CSS3):content box-shadow border-radius transform background:linear-gradient
对比下面两种书写,后者明显可阅读性更强
.card {color: #1289fb;font-family: PingFangSC, PingFangSC-Medium;height: 20px;text-align: right;margin-left: 6px;display: flex;weight: 500px;border-radius: 2px;line-height: 20px;font-size: 16px;font-weight: 500;
}
按照顺序书写:
.card {display: flex;margin-left: 6px;height: 20px;weight: 500px;border-radius: 2px;text-align: right;line-height: 20px;font-size: 16px;font-family: PingFangSC, PingFangSC-Medium;font-weight: 500;color: #1289fb;
}
这样书写除了提升代码可阅读性、快速定位样式问题外,最大的作用是减少浏览器reflow(回流),提升浏览器渲染dom的性能。
举例来说,如果将布局定位放在最后面,当浏览器在对render树解析布局的时候,遍历到position的时发现该元素是绝对定位元素,需要脱离文档流,而之前却是按照普通元素进行解析的,则不得不重新渲染,解除该元素在文档中所占位置,然而由于该元素的占位发生变化,其他元素也可能会受到它回流的影响而重新排位。(延伸:浏览器渲染主流程)。
要在项目中通过stylelint规范化属性顺序,可见文章:css规范化及解决方案
3、其他注意事项
1、不要滥用id选择器和!important
id选择器一定要慎重使用,最好用class选择器,一般项目有很多的后续迭代,很难保证这个模块是唯一的,一般用到id选择器,都是留给js使用的
此外,在开发时,有时由于css样式权重不够被覆盖,或者UI框架默认样式影响,总会有开发小伙伴为了省事儿,直接一个!important
解决,一时important一时爽,如果important泛滥,后续就很难维护;建议从权重、样式覆盖等多个方面去发现和解决问题,不要一把important梭哈!
2、scoped
scoped是一个很好的避免样式污染的方式,但使用了scoped后,对于一些全局样式、父子组件样式的穿透,也需要特别注意。
通常在vue项目中,一个.vue文件来表示一个组件,为了防止各个组件的css样式相互污染,通常做法是在style标签中加入一个scoped属性:<style type="text/css" scoped>
,它的原理是给HTML的DOM节点加一个不重复属性,如【data-v-469af010】标志唯一性,且在组件内每个样式选择器后添加一个与【data-v-469af010】相同的字段,实现类似于“作用域”的作用,达到组件样式的模块化。
在添加了scoped属性的组件中,如果引用了第三方组件,需要局部修改子组件的样式,就需要样式穿透,不同编译器可能有所区别
stylus的样式穿透 使用 >>>
,sass和less的样式穿透 使用 /deep/
如果不用scoped方法,则建议在每个组件的最外层定义一个唯一的class标签,其他样式包含在这个标签内,避免样式污染
css预处理器
CSS预处理是使用变量、函数及简单的逻辑实现更加简洁、更易于代码维护的兼容浏览器的页面样式文件,生成的目标文件都是css文件。在前端界,有三大 CSS 预处理器,分别是 SASS(SCSS), Less, Stylus。
1、基础使用 less sass stylus
使用css预处理器能够让我们的代码更简洁易写,此外还有一些变量、函数、计算等功能,引入预处理器很方便.
具体使用及文档可见预处理器详细介绍及官网
2、对比与选择
三种预处理器的具体对比可见对比一览表、深度比较,这里只简单介绍一下,总的来说,都可以允许嵌套语法、支持变量、支持运算,满足基本的开发需求,可自行选择;目前用的更多的是less及stylus
预处理器 | sass | less | stylus |
---|---|---|---|
变量 | $var-name: var-value; | @normal-with: 10px; | var-name = var-value; |
引入外部文件 | @import | @import | @import |
书写格式 | 需要{}及; | 需要{}及; | 需要{}及; |
3、常用高级用法(以less为例)
mixin混合
.bordered {border-top: dotted 1px black;border-bottom: solid 2px black;
}.post a {color: red;.bordered();
}
编译后,会将对应的样式引入
.post a {color: red;border-top: dotted 1px black;border-bottom: solid 2px black;
}
css的合并与拆分
1、css样式优先级及权重
css样式属性,按优先级展示,提到优先级就离不开权重。这是css基础,这里不再赘述,详细可见一篇详细分析css优先级的博客
简述
- 内联1000 > id 100 > class 10 > 标签 1
- 先从高等级进行比较,高等级相同时,再比较低等级的,以此类推;
- 完全相同的话,就采用后者优先原则(也就是样式覆盖);
- !important无条件绝对优先(比内联样式还要优先)
2、什么时候合并,什么时候拆分?
关于css样式的合并与拆分,我通常的方案是
- 当有大量相同样式属性时,建议合并,减少代码量
- 如果使用css预处理器,酌情使用mixin混合的方式,引入相同的样式
- 尽量避免冗余的css样式书写,多关注属性的继承
JS篇
说到优雅的JS的,这里有一篇来自蚂蚁金服的小伙伴写的文章分享给大家 [我是如何将业务代码写优雅的] (https://zhuanlan.zhihu.com/p/64354422),以下为我个人总结的在JS编程中需要特别注意的几点
- 注释注释写注释
- 不要写魔鬼数字
- 嵌套不要过深
- 合理抽取组件及函数
- 注意边界条件
详细的描述如下
注释注释写注释
重要性就不多说了,为了自己,为了他人,为了世界和平,写点注释吧!
不要写魔鬼数字
在项目中可能经常会有这样的代码:
if (sourceId === 123) {....
} else if (sourceId === 345) {....
}
诸如此类没有注释、难以理解其代表意义的常量(0、1这种)都称之为魔鬼数字。
也许当时开发你知道这些数字的含义,但当过几个月之后,或者开发人员流动以后,这些东西就会很麻烦。
通常的解决办法是:用一眼就能看懂的常量定义魔鬼数字,如:
const BEIJING = 123;
const SHANGHAI = 345
if (sourceId === BEIJING) {....
} else if (sourceId === SHANGHAI) {....
}
这样就很明确知道这两串数字代表的含义,注意这里的常量命名需要便于理解,否则还不如数字可阅读性高
嵌套不要过深
不仅css有样式层级的嵌套,js也有嵌套,这里的嵌套指的是js内的函数调用,不要盲目嵌套导致代码可阅读性差,对于可分步骤的逻辑,完全可以借助async及promise的力量。
如果见到一个函数调一个函数的方法,可能看到后面,都忘记了自己要看什么东西了。
pro1(params){...pro3(data);
}
pro2(liu) {...pro4(lili)
}
pro3(data) {...pro2(liu)
}
建议按步骤来酌情划分逻辑,如下代码可阅读性更强
async group(data) {liu = await his(data);lili = await his2(liu);
}
合理抽取组件及函数
在实际使用中,抽取一些公共组件及通用业务组件,非常有助于我们的开发,这并没有什么特别要说的。但是也不要矫枉过正
,如果随便一个小的模块都要抽取组件的话,代码维护起来也会非常困难,尤其是在后续优化及迭代需要做一些个性化设置时。
此外,对于页面内的模块的不同状态,是在模块内做判断拆分,还是直接分两个模块来写,[这篇文章] (https://zhuanlan.zhihu.com/p/64354422)已经说得很清楚,总之一切宗旨都是为了好维护。
注意边界条件
基本上测试阶段会检测出来很多的bug,但有一些bug,是当时不会出现,但后续会出现的,我们在开发的时候,要注意多考虑考虑一些边界条件和可能的变化。
举个例子,但凡出现if判断,要考虑下后续迭代
这样一段代码
if (type === "person") {.....
} else {.....
}
也许一开始,type只有两种状态:person,animal,这样写没什么问题,但或许几个月后,type增加了一种—plant,而这个type可能不止一个地方用到了,这段代码没有改动到,就会出现我们没有预料到的bug
综上,总结了一些基础的、常见的将css及js写的更优雅的方法和建议,但真正要将代码写的好,还需要更多经验的积累和技术的沉淀。最后说道,虽然技术深度影响了我们的代码质量,但一昧追求高级及冷门用法却不注重规范和可维护性,对代码质量也是有严重打击的哦!
与君共勉!
如何将前端代码写的优雅?相关推荐
- 如何把代码写的优雅一些
一.背景 写这篇博客的背景是因为今晚因为一些代码风格的原因,被主管教育了一顿,代码的好坏,影响的是整个公司的开发效率,还会影响找bug的速度,同时,对我们自身的成长也会起到阻碍作用.所以是时候规范下自 ...
- 如何用代码写一个优雅的个人简历
Person person = new Person();person.Name = "铁柱";person.WeChat = "Goog_Luck_ly";/ ...
- 如何把前端项目写成一座屎山?
作者:阿佛加德奔 原文:https://juejin.cn/post/7086735198942920712 前言 最近几年前端发展的非常快,SPA的繁荣让前端的工程化也越来越重.在很多场景下,前端的 ...
- 优雅写mysql_如何写出优雅的代码?
我 18 年在 PyCon 做过一次类似的分享 ,目的是如何写出优雅的代码.希望能部分回答这个问题,也希望与大家多多讨论.<聊聊编程原则>zhuanlan.zhihu.com 要成为合格 ...
- php代码如何写得好看,如何写出优雅的PHP代码
如何写出优雅的PHP代码 导语:PHP是一种通用开源脚本语言.语法吸收了C语言.Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域.下面我们来看看如何写出优雅的PHP代码,希望对大 ...
- 如何写出优雅的代码?
希望你的代码如同你本人一样优雅.:) 我们编写的代码,除了用于机器执行产生我们预期的效果以外,更多的时候是给人读的,这个读代码的可能是后来的维护人员,更多时候是一段时间后的作者本人. 如何能够写出优雅 ...
- 转程序员,都去写一写前端代码吧
转自: http://www.oschina.net/news/36972/programmer-write-frond-end-code 你可以认为我是一个极端的人,就像有许多人专注于自己的领域而不 ...
- 如何写出优雅的 Golang 代码
Go 语言是一门简单.易学的编程语言,对于有编程背景的工程师来说,学习 Go 语言并写出能够运行的代码并不是一件困难的事情,对于之前有过其他语言经验的开发者来说,写什么语言都像自己学过的语言其实是有问 ...
- Guava - 拯救垃圾代码,写出优雅高效,效率提升N倍
Guava 项目是 Google 公司开源的 Java 核心库,它主要是包含一些在 Java 开发中经常使用到的功能,如数据校验.不可变集合.计数集合,集合增强操作.I/O.缓存.字符串操作等.并且 ...
最新文章
- 在VS中用正则表达式查找或替换
- 如何实现搜索列表_图解:如何理解与实现散列表
- 程序员初涉江湖 宜步步为赢(转-2) 作者:IT168 职业发展顾问Leo
- flutter 的gradle下载不了怎么办
- 数据库期末总结笔记(零基础)-第三章 关系数据库SQL
- php字符编码转换问题
- 一个比较完整的pytorch项目
- kafka windows单机安装测试
- 第一次学游泳技巧_第一次学游泳作文600字(5篇)
- 太原学院的计算机科学与技术学院,太原 学院新校区计算机科学与技术
- cdr CorelDRAW Graphics Suite 2021 (v23.1.0)
- matlab dsb调制,幅度调制(AM、DSB、SSB、VSB)
- 通过pdf的url在线浏览pdf
- 微软需要Twitter来对抗Google
- 三年级江苏凤凰出版社计算机,苏教版小学信息技术三年级下册教案全集
- 收藏 | 42 款 Chrome 插件神器,你必须知道!
- HDOJ 4238 - Programming the EDSAC 阅读理解..高精度处理
- 洒扫庭除,恭候佳朋 ——知象光电欢迎广大来宾莅临TCT展会知象展位
- 春季在农村,有哪些赚钱的途径,能每月收入七八千的?
- 基于 Agora SDK 实现 Web 端的多人视频互动
热门文章
- 腾讯会议攻转守,小鱼易连守转攻
- 富士胶片首次参展贵阳数博会;佳能携多元化专业影像设备亮相CCBN2021;七彩虹建设国内首家GPU博物馆 | 全球TMT...
- java csrf_java – 如何在使用CSRF登录后启用Spring Secu...
- 什么是区块链服务网络(BSN)
- 2016-年蓝桥杯C-(A组)赛题-网友年龄
- 启发式搜索 luogu2483——[SDOI2010]魔法猪学院
- 模型泛化能力是什么意思
- 结构化思维模型的构建(多种思维参考)
- 工作站 Linux 系统下无线网卡配置
- 基于4412的dm9000驱动移植