诺锞前端开发规范

前端开发规范 v1.2.3

Copyright (c) by PT IHU URSA Team - Luna Zhou

命名规范

前言

规范等级

【必须】 :绝对,严格遵循,请照做,无条件遵守
【应该】 :强烈建议这样做,但是不强求
【禁止】 :禁令,严令禁止

Css 命名规范

  • 公用型或结构型类名应尽可能使用NEC规范(简单)或BEM规范(高级)---- 【应该】
    • 关于NEC规范
      1. NEC规范相对更简单适合锻炼页面结构意识
      2. 布局(grid)(.g-):将页面分割为几个大块,通常有头部、主体、主栏、侧栏、尾部等!
      3. 模块(module)(.m-):通常是一个语义化的可以重复使用的较大的整体!比如导航、登录、注册、各种列表、评论、搜索等!
      4. 元件(unit)(.u-):通常是一个不可再分的较为小巧的个体,通常被重复用于各种模块中!比如按钮、输入框、loading、图标等!
      5. 功能(function)(.f-):为方便一些常用样式的使用,我们将这些使用率较高的样式剥离出来,按需使用,通常这些选择器具有固定样式表现,比如清除浮动等!不可滥用!
      6. 皮肤(skin)(.s-):如果你需要把皮肤型的样式抽离出来,通常为文字色、背景色(图)、边框色等,非换肤型网站通常只提取文字色!非换肤型网站不可滥用此类!
      7. 状态(.z-):为状态类样式加入前缀,统一标识,方便识别,她只能组合使用或作为后代出现(.u-ipt.z-dis {},.m-list li.z-sel {}),具体详见命名规则的扩展相关项。
    • 关于BEM规范
      8. BEM规范的一些中文资料 ---- https://www.w3cplus.com/blog/tags/325.html
      9. 建议使用Nicolas Gallagher修改过的BEM规范 ---- https://www.cnblogs.com/dujishi/p/5862911.html
      10. BEM规范上手相对难一些,但是结构更清晰直观,也更便于维护
  • 非上述类型的样式类名 比如页面内部样式,独立样式等,请使用 “-” 链接关键字,如:“swiper-container, table-cell” ---- 【必须】(不要使用大写字母和 _ !!!---- 【禁止】)

JS命名规范

  • 命名应尽可能表达此变量 / 函数 所起的作用或所表达的含义 ---- 【应该】

  • 变量 / 函数名使用驼峰式命名法,以小写字母开头,如:“isLoading, toPage” ---- 【必须】

  • 私有(内部)变量 / 函数名以 "_" 开头配合驼峰式命名法,如:“_data, _parseStr” ---- 【应该】

  • 类 / 构造函数必须以大写字母开头,并保持驼峰式命名法 ---- 【必须】

    // 构造函数
    function HelloWorld () {}
    HelloWorld.prototype = {}
    
    // 类
    class Ajax {
        constructor () {}
        post () {}
    }
    

常规模式文件命名规范

  • 常规 .html 文件尽可能使用 “-” 链接关键词命名,如:“rule-user.html” ---- 【应该】
  • js 文件采用以小写字母开头的驼峰式命名法,如:“ruleUser.js” ---- 【应该】
  • css 等样式文件除公用文件外,其他应与其相关的 .html 文件 保持命名一致 ---- 【必须】

构建模式文件命名规范

  • 根据框架要求命名 ---- 【必须】

HTML编码风格规范

<html>
    <head>
        <meta>
        <title></title>
        <link></link>
        ...
        <script></script> <!-- 特殊JS,例如 ga、百度统计等 明确要求放置于头部的JS文件 -->
    </head>
    <body>
        ...
        <script></script> <!-- 常规JS -->
    </body>
</html>

CSS编码风格规范

css初始化(reset)

使用 Normalize.css

* {
    margin: 0;
    padding: 0;
    list-style: none;
    box-sizing: border-box;
    ...
}

使用 Sass 或 Less 等预编译工具

使用预编译工具时 请把 文件拆分,切勿全部塞在一个文件中。
以less为例

// variable.less
@gray: #8e8e8e;
@lightGray: #f1f3f5;
// mixin.less
.grayLv (@scale) {
  filter: grayscale(@scale);
}
// reset.less
* {
    margin: 0;
}
// style.less
@import 'variable'
@import 'mixin'
@import 'reset'

缩进

  • .css
    缩进 4空格

    // main.css
    
    .class {
        font-size: 16px;    
    }
    
  • 预编译
    按照预编译工具要求缩进,无明确要求的 统一缩进 2空格

    // main.less
    
    .class {
      font-size: 16px;
      .class-child {
        font-size: 20px;
      }
    }
    

环境命名

  • 生产:'production'
  • 开发:'development'
  • 测试:'test‘

Javascript编码风格规范

参考借鉴了 JavaScript Standard StyleGoogle JavaScript style guide (ES2015+ version) 并随机调查了本司前端er的日常开发习惯 做了一些修改调整

具体规则内容:
https://github.com/nc-ursateam/eslint-config-nc_ursa#readme

前端代码检查规范

ESLint

  • js 代码使用ESLint做代码检查和矫正

    引入 eslinteslint-config-nc_ursa

    npm i eslint eslint-config-nc_ursa --save-dev
    

    eslint 配置文件中的 extends修改/添加 nc_ursa

    {
        module.exports = {
            'extends': 'nc_ursa',
        }
    }
    

    使用 eslint xxx.js 命令 检查代码
    使用 eslint xxx.js --fix 命令 矫正代码

代码注释规范

追根溯源

为了能在遇到bug的时候 能更显性的责任到人
在JS源文件顶部需加入 作者信息 (JSDoc 语法 / JSDoc 中文文档 from HTML中国 / JSDoc 中文文档 )

/**
 * @author Luna <luna.zhou@normcore.com>
 * ...其他作者
 */

TODO

记录一个将要完成/之后要做的任务
JSDoc 语法 / JSDoc 中文文档 from HTML中国 / JSDoc 中文文档

/**
 * @todo Write the documentation.
 * @todo Implement this function.
 */
function foo() {
  // write me
}

TODO 注释 可简写为以下形式

// TODO xxx需求...
function foo() {
    // write me
}

注:简写形势下 TODO 必须 大写!!!

其他

大模块/function 请参照 JSDoc语法 酌情对函数/模块添加必要的注释
小型行内简要注释可用 // xxx 形式简写
JSDoc 语法 / JSDoc 中文文档 from HTML中国 / JSDoc 中文文档

文件目录规范

常规模式

static ---- 静态资源文件夹
└    css ---- 样式文件夹
└    images ---- 图片文件夹
└    js ---- js文件夹
└    font ---- 字体资源文件夹
└    libs (可选) ---- js库文件夹 (可统一归入 js文件夹内,也可独立出来)
index.html ---- 首页
${page1}.html ---- 页面不多时 可跟index平级存放页面.html文件
...
${page2} ---- 页面文件夹 (页面较多时可根据页面类别/功能/菜单 放入一个文件夹中)
└    ${page2-1}.html
└    ${page2-2}.html
└    ...
${page3}
└    ${page3-1}.html
└    ...
...

举例:
static 
└ css 
 └ style.css
 └ jobs.css
 └ ...
└ images  
 └ logo.png
└ js 
 └ main.js
 └ jobs.js
 └ ...
└ font 
 └ iconfont.ttf
└ libs (可选) 
 └ jQuery.js
index.html 
about.html 
contact 
└ contact.html
└ jobs.html

框架脚手架模式(cli)

  • 项目开发目录结构依照脚手架生成的结构

  • 编译后目录结构

    dist
    └ static ---- 静态资源文件夹
      └ css ---- 样式文件夹
      └ images ---- 图片文件夹
      └ js ---- js文件夹
      └ font ---- 字体资源文件夹
    └ index.html ---- 首页
    └ ${page1}.html ---- 页面不多时 可跟index平级存放页面.html文件
    └ ...
    └ ${page2} ---- 页面文件夹 (页面较多时可根据页面类别/功能/菜单 放入一个文件夹中)
      └ ${page2-1}.html
      └ ${page2-2}.html
      └ ...
    └ ${page3}
      └ ${page3-1}.html
      └ ...
    └ ...
    

前端发布流程

提交代码

为防止不符合规范的代码被提交到git代码库中,
所有前端项目必须先安装husky包,并添加.huskyrc.json配置文件到根目录中

npm install husky --save-dev
```µ
例:
```json
// package.json
{
  ...
  "scripts": {
    ...
    "lint": "eslint xxx",
    "hi-husky": "echo Hi Husky",
    ...
  },
  ...
}
// .huskyrc.json
{
  "hooks": {
    "pre-commit": "npm run hi-husky && npm run lint",
    ...
  }
}

由于直接在husky中使用eslint --fix命令并不会在当前提交中修正不符合规范的代码而是会把不符合规范的代码直接通过验证提交到 git库 中

所以在这里我们必须使用lint-staged来避免此问题

安装lint-staged

npm install lint-staged --save-dev

修改上述的package.json.huskyrc.json

// package.json
{
  ...
  "scripts": {
    ...
    "lint": "eslint xxx.js",
    "hi-husky": "echo Hi Husky",
    ...
  },
  "lint-staged": {
    "xxx.js": [
      "eslint --fix",
      "git add"
    ]
  }
  ...
}
// .huskyrc.json
{
  "hooks": {
    "pre-commit": "npm run hi-husky && lint-staged",
    ...
  }
}

这时我们就能看到在本地的提交中 所有的 能被eslint修正的 不符合规范的 代码都已经被修正了,倘若有无法被eslint修正的代码会显示报错并中断git commit的操作

git仓库命名

${年份}${品牌}${项目名}${项目}(例如:小程序/H5/管理后台 等)${前端/后端}

Example:

2019_fanta_summar-internal_miniprogram_frontend
2019_castrol_owned-media_admin_frontend

注意 _-

一些关于习惯的小Tips

为了统一代码风格开发习惯,尤其是在团队作业中能更好的互相理解,更好的可读性

对一些习惯 做一些非强制性的 注意点

  • 把多次复用的目标存入一个变量中
  • 合理使用解构
  • 不要使用不明所以、意义不明的 值/变量 【此条强制】

// bad
$('div').click();
$('div').on();
...


// good
var div = $('div');
div.click();
	.on();
// bad
const food = {
	apple: ret.data.apple,	// 这样的写法太过繁琐,内容一旦多一些就会显得很杂乱,不直观
	pear: ret.data.pear,
	meat: ret.data.meat
}


food = {...ret.data} // 当ret为接口返回的内容时,别人并不知道 这个 ret 里面包含了些什么,food 要用的是什么,这样的解构用法很容易让人困惑到底用了哪些值,并且容易把不必要的内容也一并加入到 food 中


// good
var _data = ret.data;
var food = {
	apple: _data.apple,
	pear: _data.pear,
	meat: _data.meat
}


const {apple, pear, meat} = ret.data;
const food = {
	apple,
	pear,
	meat
}
// bad
obj = {
	success: function(a) {
		console.log(a);
	},
	fail: function(a) {
		console.log(a);
	},
	complete: function(a) {
		console.log(a);
	}
}


// good
obj = {
	success: function(res) {
		console.log(res);
	},
	fail: function(err) {
		console.log(err);
	},
	complete: function(res) {
		console.log(res);
	}
}