[关闭]
@yangfch3 2017-03-05T18:10:21.000000Z 字数 3958 阅读 2543

前端编码推荐规范及实践指引(一)

FE


为什么需要规范

好的代码应该是让人阅读起来赏心悦目的,但是在实际项目中(尤其是项目体量一旦变大)想做到这一点却十分困难,现实情况是每次 debug 或者代码重构都是一件让人十分头疼的事,原因很多:

  1. 人员流动
  2. 团队惰性
  3. 缺乏代码审查(Code Review)
  4. 没有利用代码约束的技术或工具
  5. ……

尤其前端方向(HTML、CSS 和 JavaScript)语法是松散灵活的,没有约束指导后大部分团队在实际项目中的现状是:

  1. 命名冲突
  2. 代码语义化不强,不明所以
  3. 大量无用的历史冗余代码,又不敢随意删除
  4. 复用性(模块性)不强
  5. ……

而我们可以对此采取哪些措施呢?

  1. 制定编码规范
  2. 严格执行编码规范
  3. 团队代码审查
  4. 宁可相信程序也不要相信人,利用 Lint 工具/IDE/插件 来提高代码质量

本文尝试总结一套前端编码规范,并将介绍相关的辅助工具以达到实践指引的目的。

HTML/CSS 规范

为最大限度解决协同合作过程中出现的命名冲突问题、方便理解代码上下文、提高代码的执行效率,同时缩短项目交接时间、有必要制定一套简单易用的命名规范。基本原则是 class 需要遵循其代表的功能语义,模块化开发,不同业务模块使用不同前缀,公共部门使用项目缩写为前缀。

—— QMUI Web

基本要求:

  1. 命名简短、语义化、忌拼音、忌生僻缩写
  2. 标签语义化(反面:一路 div 到底)
  3. 基本符合 W3C Markup ValidationW3C CSS Validation 检测规则

推荐规范:

  1. UI 库/框架前缀,公共组件前缀,业务逻辑前缀
  2. 推荐 _ 做为 层级 连接符,- 承担功能前缀或后缀链接符
  3. 单词如过长或不便拆分则允许多单词小驼峰的写法

    1. <div class="profile_cnt">
    2. <div class="profile_cnt_title"></div>
    3. <div class="profile_cnt_txtErrWrap"></div>
    4. </div>
  4. 嵌套语义化 DOM 结构(父子关系)
  5. 同级扩展关系以大写区分
  6. id 或 js- 前缀类名供 JS 专用

    1. <div class="profile_cnt_btn js-profileCntBtn"></div>
    2. <div class="profile_cnt_btn" id="profileCntBtn"></div>
  7. ……

1. 关于前缀

一般我们的项目的 UI 代码会由数个部分组成:

  1. 公司/部门/团队级基础公共 UI 组件(可能没有,视情况而定)
  2. 针对项目制定的 UI 组件
  3. 具体的模块代码

最终前端 UI 的呈现就是上述三部分的拼合与复写。

现假设 Hope 公司的情况如下:

公司经过了许许多多项目的开发,总结了一套适用于所有(大部分)项目的 UI 组件,叫做 Hope UI,已封装好,可方便地供所有项目使用。

Hope 公司正在做一个项目,项目代号为 Chem,设计师已经绘制出了一套 UIKit。

代码实例:

  1. <!-- hp 为团队公共 UI 组件前缀 -->
  2. <!-- ce 为项目 UI 组件前缀 -->
  3. <a class="hp_btn ce_btn profile_cnt_btn" href="javascript:;">按钮1</a>

2. 嵌套结构

先看一段代码实例:

  1. <div class="profile_header">
  2. <div class="profile_header_title">
  3. <span class="profile_header_title_icon hp_icon ce_icon ce_icon_hand"></span>
  4. <h1 class="profile_header_title_txt">
  5. </h1>
  6. </div>
  7. </div>
  8. <div class="profile_cnt">
  9. ...
  10. </div>

像上面一样书写什么好处呢?

  1. DOM 结构非常清晰,看到类名便知晓其父级结构、子级结构
  2. 再也不需要绞尽脑汁编类名了
  3. 命名的冲突不会再出现
  4. 如果使用了 Sass/Less 来编写预处理的 CSS 时就更加幸福了,如下:

    1. .profile {
    2. &_header {
    3. height: 150px;
    4. background-color: #666;
    5. &_title {
    6. display: inline-block
    7. &_txt {
    8. font-size: 18px;
    9. }
    10. }
    11. }
    12. &_cnt {
    13. background-color: #ccc
    14. }
    15. }
  5. ……

3. 同级特异扩展

先看如下代码:

  1. <div class="profile_header">
  2. <div class="profile_header_title">
  3. </div>
  4. <!-- 注意这里的 `-Red` -->
  5. <div class="profile_header_title profile_header_title-Red">
  6. </div>
  7. </div>
  8. <div class="profile_cnt">
  9. ...
  10. </div>

上面的 profile_header_titleprofile_header_title-Red 是同一级的,所以二者都有 profile_header_title 部分,-Red 的首字母大写并使用-(而非_)连接,表示是前一级的特异扩展,而不是父子 DOM 的关系。

4. 当类名层级太长

类名一般做好不要超过 5-6 个层级,即 _ 分隔的部分不要多达 6 个以上。

当理论类名层级过长,例如:

  1. ...
  2. <div class="profile_cnt_nav_list_item_left_title">
  3. </div>
  4. ...

那么遵循以下原则:

  1. 不允许缩写(看代码的人已经不知道你写的是什么了):

    1. <!-- not good -->
    2. class="pcnlil_title"
  2. 第层不能省
  3. 省前不省后(省略位置考前的)
  4. 其后代 DOM 需要与其省略一直
  1. ...
  2. <div class="profile_cnt_nav_list_item_left_title">
  3. </div>
  4. <!-- To -->
  5. <div class="profile_list_item_left_title">
  6. </div>
  7. ...

4. JS DOM 的特征化识别

  1. 使用 js- 前缀 + 小驼峰 类名,例如:

    1. <div class="profile_header js-profileHeader">
    2. </div>
  2. 或使用小驼峰 id(尽可能用类名来小驼峰化)

    1. <div class="profile_header" id="profileHeader">
    2. </div>

5. 注释规范

HTML 注释要注意注释内容与前后 - 之间的空格:

  1. <!-- comments come to here -->

CSS 单行注释注意内容与前后 * 之间的空格:

  1. /* comments come to here */

CSS 多行注释:

  1. /**
  2. * comments come to here
  3. */

CSS 重要注释(不会被编译、压缩工具丢弃)

  1. /*!
  2. * important comments come to here
  3. */

6. 其他细则

团队可参考以下资料自己整理制定:

  1. Popular Coding Convention on Github
  2. Code Guide - en
  3. Code Guide - zh-cn

JavaScript 规范

1. 命名

一般变量与函数名统一采用驼峰,禁止出现 _ - 连接的形式:

  1. // good
  2. var totalNum = 10;
  3. function getTotalNum() {
  4. // ...
  5. }
  6. // not good
  7. var total-num = 10;
  8. var total_num = 10;

常量采用全大写,单词间以 _ 分隔:

  1. // good
  2. const MAX_COUNT = 20; // ES6 写法
  3. var MAX_COUNT = 20; // ES5 写法

jQuery 对象使用 $ 做为特征字符识别:

  1. var $body = $('body');

2. 模块化

模块化现在已经成了业界的共识,大大提高了我们的开发效率,改善了我们的开发体验,提高了的代码的复用,降低了 Debug 的时间成本。

模块化需要花费比较大的篇幅讲解,并且需要根据团队的需求进行特异性定制,本文在此不赘述。

3. 其他细则

其他细则就不必说了,因为 ESLint 能帮助我们做剩下的代码规范检查工作。许多十分愚蠢与不经意的错误能够得到极大程度的避免,开发效率提升不止一点。

现在主流的开源前端项目基本上全部使用了 ESLint 做为其审查工具以保证代码的质量与持续开发,学习与配置使用 ESLint 是一劳永逸的事情,有助于团队成员持续 养成代码洁癖

ESLint 推荐配置文件 .eslintrc.js

  1. module.exports = {
  2. extends: ['standard', 'eslint:recommended'],
  3. parserOptions: {
  4. ecmaVersion: 6,
  5. sourceType: 'module'
  6. },
  7. env: {
  8. es6: true,
  9. node: true,
  10. browser: true,
  11. mocha: true,
  12. amd: true,
  13. jquery: true
  14. },
  15. plugins: [
  16. 'standard'
  17. ],
  18. global: {
  19. ENV: true
  20. },
  21. rules: {
  22. semi: [1, 'always'],
  23. indent: [2, 4, {
  24. SwitchCase: 1
  25. }],
  26. quotes: [2, 'single'],
  27. 'linebreak-style': [2, 'unix'],
  28. 'no-console': [1],
  29. 'no-unused-vars': [1]
  30. }
  31. };

下篇预告

本文或详细或粗糙地讲述了 HTML/CSS/JavaScript 的规范问题,没提到的部分网上都有相关文章或资料可查阅。

下篇文章将介绍各个代码审查工具(ESLint、CSSLint、Sublimelinter 相关插件等)的使用与配置。

下下篇文章将讲述前端的模块化开发,如何配置模块化、工程化、自动化的工程架构,以及如何将各个辅助工具集成到我们的工程架构里。

舒适的开发环境来源于规范的强力执行,以及对各种辅助工具的充分应用,不要写出一大堆难懂、冗余、不规范的代码让将来的自己和同事来帮你填坑。


参考资料:
1. QMUI Web 编码规范

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注