# 前端开发规范 **Repository Path**: xiawang1024/front_rules ## Basic Information - **Project Name**: 前端开发规范 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-04-13 - **Last Updated**: 2021-10-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* + [命名规范](#%E5%91%BD%E5%90%8D%E8%A7%84%E8%8C%83) - [项目命名](#%E9%A1%B9%E7%9B%AE%E5%91%BD%E5%90%8D) - [目录命名](#%E7%9B%AE%E5%BD%95%E5%91%BD%E5%90%8D) - [JS 文件命名](#js-%E6%96%87%E4%BB%B6%E5%91%BD%E5%90%8D) - [CSS, SCSS 文件命名](#css-scss-%E6%96%87%E4%BB%B6%E5%91%BD%E5%90%8D) - [HTML 文件命名](#html-%E6%96%87%E4%BB%B6%E5%91%BD%E5%90%8D) + [HTML 规范](#html-%E8%A7%84%E8%8C%83) - [语法](#%E8%AF%AD%E6%B3%95) - [HTML5 doctype](#html5-doctype) - [lang 属性](#lang-%E5%B1%9E%E6%80%A7) - [CHARSET](#charset) - [引入 css,js](#%E5%BC%95%E5%85%A5-cssjs) - [减少标签数量](#%E5%87%8F%E5%B0%91%E6%A0%87%E7%AD%BE%E6%95%B0%E9%87%8F) - [id,class 及属性的命名](#idclass-%E5%8F%8A%E5%B1%9E%E6%80%A7%E7%9A%84%E5%91%BD%E5%90%8D) - [实用高于完美](#%E5%AE%9E%E7%94%A8%E9%AB%98%E4%BA%8E%E5%AE%8C%E7%BE%8E) - [WebApp Meta](#webapp-meta) + [CSS规范](#css%E8%A7%84%E8%8C%83) - [代码规范](#%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83) - [编码规范](#%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83) - [文档内嵌样式表编码](#%E6%96%87%E6%A1%A3%E5%86%85%E5%B5%8C%E6%A0%B7%E5%BC%8F%E8%A1%A8%E7%BC%96%E7%A0%81) - [文档外链样式表编码](#%E6%96%87%E6%A1%A3%E5%A4%96%E9%93%BE%E6%A0%B7%E5%BC%8F%E8%A1%A8%E7%BC%96%E7%A0%81) - [关于 @charset](#%E5%85%B3%E4%BA%8E-charset) - [约定](#%E7%BA%A6%E5%AE%9A) - [代码风格](#%E4%BB%A3%E7%A0%81%E9%A3%8E%E6%A0%BC) - [代码格式化](#%E4%BB%A3%E7%A0%81%E6%A0%BC%E5%BC%8F%E5%8C%96) - [代码大小写](#%E4%BB%A3%E7%A0%81%E5%A4%A7%E5%B0%8F%E5%86%99) - [选择器](#%E9%80%89%E6%8B%A9%E5%99%A8) - [代码缩进](#%E4%BB%A3%E7%A0%81%E7%BC%A9%E8%BF%9B) - [分号](#%E5%88%86%E5%8F%B7) - [代码易读性](#%E4%BB%A3%E7%A0%81%E6%98%93%E8%AF%BB%E6%80%A7) - [属性值引号](#%E5%B1%9E%E6%80%A7%E5%80%BC%E5%BC%95%E5%8F%B7) - [属性书写顺序](#%E5%B1%9E%E6%80%A7%E4%B9%A6%E5%86%99%E9%A1%BA%E5%BA%8F) - [CSS3浏览器私有前缀写法](#css3%E6%B5%8F%E8%A7%88%E5%99%A8%E7%A7%81%E6%9C%89%E5%89%8D%E7%BC%80%E5%86%99%E6%B3%95) - [注释规范](#%E6%B3%A8%E9%87%8A%E8%A7%84%E8%8C%83) - [单行注释](#%E5%8D%95%E8%A1%8C%E6%B3%A8%E9%87%8A) - [模块注释](#%E6%A8%A1%E5%9D%97%E6%B3%A8%E9%87%8A) - [文件信息注释](#%E6%96%87%E4%BB%B6%E4%BF%A1%E6%81%AF%E6%B3%A8%E9%87%8A) - [重置样式](#%E9%87%8D%E7%BD%AE%E6%A0%B7%E5%BC%8F) - [移动端](#%E7%A7%BB%E5%8A%A8%E7%AB%AF) - [PC端](#pc%E7%AB%AF) - [媒体查询](#%E5%AA%92%E4%BD%93%E6%9F%A5%E8%AF%A2) - [常用查询语句](#%E5%B8%B8%E7%94%A8%E6%9F%A5%E8%AF%A2%E8%AF%AD%E5%8F%A5) - [命名](#%E5%91%BD%E5%90%8D) + [图片规范](#%E5%9B%BE%E7%89%87%E8%A7%84%E8%8C%83) - [命名](#%E5%91%BD%E5%90%8D-1) - [图片格式](#%E5%9B%BE%E7%89%87%E6%A0%BC%E5%BC%8F) - [内容图](#%E5%86%85%E5%AE%B9%E5%9B%BE) - [背景图](#%E8%83%8C%E6%99%AF%E5%9B%BE) - [图片大小](#%E5%9B%BE%E7%89%87%E5%A4%A7%E5%B0%8F) - [图片质量](#%E5%9B%BE%E7%89%87%E8%B4%A8%E9%87%8F) + [javascript 规范](#javascript-%E8%A7%84%E8%8C%83) - [语言规范](#%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83) - [类型](#%E7%B1%BB%E5%9E%8B) - [引用](#%E5%BC%95%E7%94%A8) - [对象](#%E5%AF%B9%E8%B1%A1) - [数组](#%E6%95%B0%E7%BB%84) - [解构赋值](#%E8%A7%A3%E6%9E%84%E8%B5%8B%E5%80%BC) - [字符串](#%E5%AD%97%E7%AC%A6%E4%B8%B2) - [函数](#%E5%87%BD%E6%95%B0) - [原型](#%E5%8E%9F%E5%9E%8B) - [模块](#%E6%A8%A1%E5%9D%97) - [迭代器](#%E8%BF%AD%E4%BB%A3%E5%99%A8) - [对象属性](#%E5%AF%B9%E8%B1%A1%E5%B1%9E%E6%80%A7) - [变量声明](#%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E) - [变量提升](#%E5%8F%98%E9%87%8F%E6%8F%90%E5%8D%87) - [比较和相等](#%E6%AF%94%E8%BE%83%E5%92%8C%E7%9B%B8%E7%AD%89) - [分号](#%E5%88%86%E5%8F%B7-1) - [标准特性](#%E6%A0%87%E5%87%86%E7%89%B9%E6%80%A7) - [eval()](#eval) - [with() {}](#with-) - [for-in 循环](#for-in-%E5%BE%AA%E7%8E%AF) - [修改内置对象的原型](#%E4%BF%AE%E6%94%B9%E5%86%85%E7%BD%AE%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%8E%9F%E5%9E%8B) - [编码规范](#%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83-1) - [单行代码块](#%E5%8D%95%E8%A1%8C%E4%BB%A3%E7%A0%81%E5%9D%97) - [大括号风格](#%E5%A4%A7%E6%8B%AC%E5%8F%B7%E9%A3%8E%E6%A0%BC) - [变量命名](#%E5%8F%98%E9%87%8F%E5%91%BD%E5%90%8D) - [拖尾逗号](#%E6%8B%96%E5%B0%BE%E9%80%97%E5%8F%B7) - [逗号空格](#%E9%80%97%E5%8F%B7%E7%A9%BA%E6%A0%BC) - [逗号风格](#%E9%80%97%E5%8F%B7%E9%A3%8E%E6%A0%BC) - [计算属性的空格](#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7%E7%9A%84%E7%A9%BA%E6%A0%BC) - [拖尾换行](#%E6%8B%96%E5%B0%BE%E6%8D%A2%E8%A1%8C) - [函数调用](#%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8) - [缩进](#%E7%BC%A9%E8%BF%9B) - [对象字面量的键值缩进](#%E5%AF%B9%E8%B1%A1%E5%AD%97%E9%9D%A2%E9%87%8F%E7%9A%84%E9%94%AE%E5%80%BC%E7%BC%A9%E8%BF%9B) - [构造函数首字母大写](#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E9%A6%96%E5%AD%97%E6%AF%8D%E5%A4%A7%E5%86%99) - [构造函数的参数](#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E7%9A%84%E5%8F%82%E6%95%B0) - [链式调用](#%E9%93%BE%E5%BC%8F%E8%B0%83%E7%94%A8) - [空行](#%E7%A9%BA%E8%A1%8C) - [链式赋值](#%E9%93%BE%E5%BC%8F%E8%B5%8B%E5%80%BC) - [变量声明](#%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E-1) - [分号](#%E5%88%86%E5%8F%B7-2) - [代码块空格](#%E4%BB%A3%E7%A0%81%E5%9D%97%E7%A9%BA%E6%A0%BC) - [函数声明的空格](#%E5%87%BD%E6%95%B0%E5%A3%B0%E6%98%8E%E7%9A%84%E7%A9%BA%E6%A0%BC) - [操作符的空格](#%E6%93%8D%E4%BD%9C%E7%AC%A6%E7%9A%84%E7%A9%BA%E6%A0%BC) + [开发约定](#%E5%BC%80%E5%8F%91%E7%BA%A6%E5%AE%9A) - [主要工具有:](#%E4%B8%BB%E8%A6%81%E5%B7%A5%E5%85%B7%E6%9C%89) + [git commit规范](#git-commit%E8%A7%84%E8%8C%83) - [type:commit类型](#typecommit%E7%B1%BB%E5%9E%8B) - [scope:commit影响的范围](#scopecommit%E5%BD%B1%E5%93%8D%E7%9A%84%E8%8C%83%E5%9B%B4) - [subject:commit的概述](#subjectcommit%E7%9A%84%E6%A6%82%E8%BF%B0) - [其它注意事项](#%E5%85%B6%E5%AE%83%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9) - [commit Demo](#commit-demo) # 前端开发规范 ## 命名规范 **所有命名应避免拼音命名** ### 项目命名 项目名全部采用小写方式,多个单词组成时, 以中划线分隔 例:my-project-name ### 目录命名 参照项目命名规则 有复数结构时,要采用复数命名法 例:scripts, styles, images, data-models ### JS 文件命名 参照项目命名规则 例:account-model.js ### CSS, SCSS 文件命名 参照项目命名规则 例:retina-sprites.scss ### HTML 文件命名 参照项目命名规则 例:error-report.html --- ## HTML 规范 ### 语法 * 缩进使用 soft tab(2 个空格); * 嵌套的节点应该缩进; * 在属性上,使用双引号,不要使用单引号; * 属性名全小写,用中划线做分隔符。 ### HTML5 doctype ``` html ``` ### lang 属性 ``` html ``` ### CHARSET ``` html ``` ### 引入 css,js 根据HTML5规范, 通常在引入CSS和JS时不需要指明 type,因为 text/css 和 text/javascript 分别是他们的默认值。 ``` html ``` ### 减少标签数量 在编写HTML代码时,需要尽量避免多余的父节点; 很多时候,需要通过迭代和重构来使HTML变得更少。 ``` html ``` ### id,class 及属性的命名 参考css,scss规范中的命名 ### 实用高于完美 尽量遵循HTML标准和语义,但是不应该以浪费实用性作为代价; 任何时候都要用尽量小的复杂度和尽量少的标签来解决问题。 ### WebApp Meta ``` html ``` --- ## CSS规范 ### 代码规范 #### 编码规范 CSS样式表是一个序列通用字符集,传输和存储过程中,这些字符必须由支持 US-ASCII(例如 UTF-8, ISO 8859-x, SHIFT JIS 等)字符编码方式编译 ##### 文档内嵌样式表编码 > When a style sheet is embedded in another document, such as in the STYLE element or "style" attribute of HTML, the style sheet shares the character encoding of the whole document. 当样式出现在其它文档,如 HTML 的 STYLE 标签或标签属性 "style",样式的编码由文档的决定。 ##### 文档外链样式表编码 > When a style sheet resides in a separate file, user agents must observe the following priorities when determining a style sheet's character encoding (from highest priority to lowest): > 1. An HTTP "charset" parameter in a "Content-Type" field (or similar parameters in other protocols) > 2. BOM and/or @charset > 3. or other metadata from the linking mechanism (if any) > 4. charset of referring style sheet or document (if any) > 5. Assume UTF-8 文档外链样式表的编码可以由以下各项按照由高到低的优先级顺序决定: 1. HTTP “Content-Type” 字段参数 “charset”(或其它协议相似的参数) 2. BOM(byte-order mark)和(或)@charset 3. Link 中的元数据设置(如果有的话) 4. 引用样式表字符集或文档编码(如果有的话) 5. 假定为 UTF-8 编码 ##### 关于 @charset > Authors using an @charset rule must place the rule at the very beginning of the style sheet, preceded by no characters. (If a byte order mark is appropriate for the encoding used, it may precede the @charset rule.) > @charset must be written literally, i.e., the 10 characters '@charset "' (lowercase, no backslash escapes), followed by the encoding name, followed by '"; '. * @charset规则一定要在样式文件的第一行首个字符位置开始,否则的话就会有机会让 BOM 设置生效(如果有设置 BOM 的话)而优于 @charset 作为样式表的编码 * `@charset "";` 一定要写上,并且用小写字母,不能出现转义符 ##### 约定 * 样式文件必须写上 @charset 规则,并且一定要在样式文件的第一行首个字符位置开始写,编码名用 “UTF-8” * 字符 `@charset "";` 都用小写字母,不能出现转义符,编码名允许大小混写 * 考虑到在使用“UTF-8”编码情况下 BOM 对代码的污染和编码显示的问题,在可控范围下,坚决不使用 BOM。(更多关于 BOM 可参考 [BOM的介绍](https://zh.wikipedia.org/wiki/%E4%BD%8D%E5%85%83%E7%B5%84%E9%A0%86%E5%BA%8F%E8%A8%98%E8%99%9F) 和 [「带 BOM 的 UTF-8」和「无 BOM 的 UTF-8」有什么区别?](http://www.zhihu.com/question/20167122) ) *推荐:* ``` css @charset "UTF-8"; .jdc {} ``` *不推荐:* ``` css /** * @desc File Info * @author Author Name * @date 2015-10-10 */ /* @charset规则不在文件首行首个字符开始 */ @charset "UTF-8"; .jdc {} ``` ``` css @CHARSET "UTF-8"; /* @charset规则没有用小写 */ .jdc {} ``` ``` css /* 无@charset规则 */ .jdc {} ``` 更多关于样式编码:[CSS style sheet representation](http://www.w3.org/TR/2011/REC-CSS2-20110607/syndata.html#charset) #### 代码风格 ##### 代码格式化 样式书写一般有两种:一种是紧凑格式 (Compact) ``` .jdc{display:block;width:50px;} ``` 一种是展开格式(Expanded) ``` css .jdc { display: block; width: 50px; } ``` **约定** 统一使用展开格式书写样式 ##### 代码大小写 样式选择器,属性名,属性值关键字全部使用小写字母书写。 ``` css /* 推荐 */ .jdc { display: block; } /* 不推荐 */ .JDC { DISPLAY: BLOCK; } ``` ##### 选择器 * 尽量不用通用选择器 `*` * 不使用 ID 选择器 * 不使用无具体语义定义的标签选择器 ``` css /* 推荐 */ .jdc { ... } .jdc li { ... } .jdc li p { ... } /* 不推荐 */ * { ... } #jdc { ... } .jdc div { ... } ``` ##### 代码缩进 统一使用2个空格进行代码缩进,使得各编辑器表现一致(各编辑器有相关配置) ``` css .jdc { width: 100%; height: 100%; } ``` ##### 分号 每个属性声明末尾都要加分号; ``` css .jdc { width: 100%; height: 100%; } ``` ##### 代码易读性 左括号与类名之间一个空格,冒号与属性值之间一个空格 *推荐:* ``` css .jdc { width: 100%; } ``` *不推荐:* ``` .jdc{ width:100%; } ``` 逗号分隔的取值,逗号之后一个空格 *推荐:* ``` css .jdc { box-shadow: 1px 1px 1px #333, 2px 2px 2px #ccc; } ``` *不推荐:* ``` .jdc { box-shadow: 1px 1px 1px #333,2px 2px 2px #ccc; } ``` 为单个css选择器或新申明开启新行 *推荐:* ``` css .jdc, .jdc_logo, .jdc_hd { ... } .nav { ... } ``` *不推荐:* ``` .jdc, jdc_logo, .jdc_hd { ... }.nav{ ... } ``` 颜色值 `rgb()` `rgba()` `hsl()` `hsla()` `rect()` 中不需有空格,且取值不要带有不必要的 0 *推荐:* ``` css .jdc { color: rgba(255, 255, 255, .5); } ``` *不推荐:* ``` .jdc { color: rgba( 255, 255, 255, 0.5 ); } ``` 属性值十六进制数值能用简写的尽量用简写 *推荐:* ``` css .jdc { color: #fff; } ``` *不推荐:* ``` css .jdc { color: #ffffff; } ``` 不要为 `0` 指明单位 *推荐:* ``` css .jdc { margin: 0 10px; } ``` *不推荐:* ``` css .jdc { margin: 0px 10px; } ``` ##### 属性值引号 css属性值需要用到引号时,统一使用单引号 ``` css /* 推荐 */ .jdc { font-family: 'Hiragino Sans GB'; } /* 不推荐 */ .jdc { font-family: "Hiragino Sans GB"; } ``` ##### 属性书写顺序 建议遵循以下顺序: 1. 布局定位属性:display / position / float / clear / visibility / overflow 2. 自身属性:width / height / margin / padding / border / background 3. 文本属性:color / font / text-decoration / text-align / vertical-align / white- space / break-word 4. 其他属性(CSS3):content / cursor / border-radius / box-shadow / text-shadow / background:linear-gradient ... ``` css .jdc { display: block; position: relative; float: left; width: 100px; height: 100px; margin: 0 10px; padding: 20px 0; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; color: #333; background: rgba(0, 0, 0, .5); -webkit-border-radius: 10px; -moz-border-radius: 10px; -o-border-radius: 10px; -ms-border-radius: 10px; border-radius: 10px; } ``` [mozilla官方属性顺序推荐](https://www.mozilla.org/css/base/content.css) ##### CSS3浏览器私有前缀写法 CSS3 浏览器私有前缀在前,标准前缀在后 ``` css .jdc { -webkit-border-radius: 10px; -moz-border-radius: 10px; -o-border-radius: 10px; -ms-border-radius: 10px; border-radius: 10px; } ``` 更多关于浏览器私有前辍写法:[#Vendor-specific extensions](http://www.w3.org/TR/2011/REC-CSS2-20110607/syndata.html#vendor-keywords) --- ### 注释规范 > Comments begin with the characters `/*` and end with the characters `*/` . They may occur anywhere outside other tokens, and their contents have no influence on the rendering. Comments may not be nested. * 注释以字符 `/*` 开始,以字符 `*/` 结束 * 注释不能被嵌套 ``` /*Comment Text*/ ``` #### 单行注释 注释内容第一个字符和最后一个字符都是一个空格字符,单独占一行,行与行之间相隔一行 *推荐:* ``` css /* Comment Text */ .jdc {} /* Comment Text */ .jdc {} ``` *不推荐:* ``` css /*Comment Text*/ .jdc { display: block; } .jdc { display: block; /*Comment Text*/ } ``` #### 模块注释 注释内容第一个字符和最后一个字符都是一个空格字符, `/*` 与 模块信息描述占一行,多个横线分隔符 `-` 与 `*/` 占一行,行与行之间相隔两行 *推荐:* ``` css /* Module A ---------------------------------------------------------------- */ .mod_a {} /* Module B ---------------------------------------------------------------- */ .mod_b {} ``` *不推荐:* ``` css /* Module A ---------------------------------------------------- */ .mod_a {} /* Module B ---------------------------------------------------- */ .mod_b {} ``` #### 文件信息注释 在样式文件编码声明 `@charset` 语句下面注明页面名称、作者、创建日期等信息 ``` css @charset "UTF-8"; /** * @desc File Info * @author Author Name * @date 2015-10-10 */ ``` 更多关于CSS注释:[#Comments](http://www.w3.org/TR/2011/REC-CSS2-20110607/syndata.html#comments) --- ### 重置样式 #### 移动端 ``` * { -webkit-tap-highlight-color: transparent; outline: 0; margin: 0; padding: 0; vertical-align: baseline; } html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, menu, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, main, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section { display: block; } /* HTML5 hidden-attribute fix for newer browsers */ *[hidden] { display: none; } body { line-height: 1; } menu, ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; } img{ border: none; } /* 去除safari中默认的input样式 */ input[type="submit"],input[type="reset"],input[type="button"],input:focus,button:focus,select:focus,textarea:focus{ outline: none;} input{-webkit-appearance:none; resize: none; border-radius: 0;} ``` #### PC端 ``` html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, menu, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, main, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section { display: block; } /* HTML5 hidden-attribute fix for newer browsers */ *[hidden] { display: none; } body { line-height: 1; } menu, ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; } img{ border: none; } a { text-decoration: none; color: #333; } a:hover { text-decoration: underline; } ``` ### 媒体查询 设备尺寸参考 :[Mobile devices](http://mydevice.io/devices/) 媒体查询类型浏览器支持情况:[CSS3 Media Queries overview](http://cssmediaqueries.com/overview.html) #### 常用查询语句 判断设备横竖屏 ``` /* 横屏 */ @media all and (orientation :landscape) { } /* 竖屏 */ @media all and (orientation :portrait) { } ``` 判断设备宽高 ``` /* 设备宽度大于 320px 小于 640px */ @media all and (min-width:320px) and (max-width:640px) { } ``` 判断设备像素比 ``` /* 设备像素比为 1 */ @media only screen and (-webkit-min-device-pixel-ratio: 1), only screen and (min-device-pixel-ratio: 1) { } /* 设备像素比为 1.5 */ @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) { } /* 设备像素比为 2 */ @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) { } ``` ### 命名 - 类名使用小写字母,以下划线“-”分隔 - id采用驼峰式命名 - scss中的变量、函数、混合、placeholder采用驼峰式命名 ``` css /* class */ .element-content { ...; } /* id */ #myDialog { ...; } /* 变量 */ $colorBlack: #000; /* 函数 */ @function pxToRem($px) { ...; } /* 混合 */ @mixin centerBlock { ...; } /* placeholder */ %myDialog { ...; } ``` --- ## 图片规范 ### 命名 参照项目命名规则 图片命名建议以以下顺序命名 图片业务(可选) +(icon-)图片功能类别(必选)+ 图片模块名称(必选) + 图片精度(可选) * 图片业务: + wx:微信 * 图片功能类别: + mod:是否公共,可选 + icon:模块类固化的图标 + logo:LOGO 类 + btn:按钮 + bg:可平铺或者大背景 * 图片模块名称: + useravatar:用户头像 * 图片精度: + Retian:@2x | @3x ### 图片格式 常见的图片格式有 GIF、PNG8、PNG24、JPEG、WEBP,根据图片格式的特性和场景需要选取适合的图片格式。 #### 内容图 内容图多以商品图等照片类图片形式存在,颜色较为丰富,文件体积较大 * 优先考虑 JPEG 格式,条件允许的话优先考虑 WebP 格式 * 尽量不使用 PNG 格式,PNG8 色位太低,PNG24 压缩率低,文件体积大 #### 背景图 背景图多为图标等颜色比较简单、文件体积不大、起修饰作用的图片 * PNG 与 GIF 格式,优先考虑使用 PNG 格式, PNG 格式允许更多的颜色并提供更好的压缩率 * 图像颜色比较简单的,如纯色块线条图标,优先考虑使用 PNG8 格式,避免不使用 JPEG 格式 * 图像颜色丰富而且图片文件不太大的(40KB 以下)或有半透明效果的优先考虑 PNG24 格式 * 图像颜色丰富而且文件比较大的(40KB - 200KB)优先考虑 JPEG 格式 * 条件允许的,优先考虑 WebP 代替 PNG 和 JPEG 格式 ### 图片大小 PC平台单张的图片的大小不应大于 200KB。 移动平台单张的图片的大小不应大于 100KB。 ### 图片质量 上线的图片都应该经过压缩处理,压缩后的图片不应该出现肉眼可感知的失真区域 60质量的JPEG格式图片与质量大于60的相比,肉眼已看不出明显的区别,因此保存 JPEG 图的时候,质量一般控制在60,若保真度要求高的图片可适量提高到 80,图片大小控制在 200KB 以内 --- ## javascript 规范 ### 语言规范 JavaScript 是一种客户端脚本语言,这里列出了编写 JavaScript 时需要遵守的规则。 #### 类型 * 基本类型 + 字符串 + 数值 + 布尔类型 + null + undefined ``` js const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // 1, 9 ``` * 复杂类型 + object + array + function ``` js const foo = [1, 2, 3]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // 9, 9 ``` #### 引用 `const` 和 `let` 都是块级作用域, `var` 是函数级作用域 * 对所有引用都使用 `const` ,不要使用 `var` ``` js // bad var a = 1; var b = 2; // good const a = 1; const b = 2; ``` * 如果引用是可变动的,则使用 `let` ``` js // bad var count = 1; if (count < 10) { count += 1; } // good let count = 1; if (count < 10) { count += 1; } ``` #### 对象 * 请使用字面量值创建对象 ``` js // bad const a = new Object {} // good const a = {} ``` * 别使用保留字作为对象的键值,这样在 IE8 下不会运行 ``` js // bad const a = { default: {}, // default 是保留字 common: {}, }; // good const a = { defaults: {}, common: {}, }; ``` * 请使用对象方法的简写方式 ``` js // bad const item = { value: 1, addValue: function(val) { return item.value + val; }, }; // good const item = { value: 1, addValue(val) { return item.value + val; }, }; ``` * 请使用对象属性值的简写方式 ``` js const job = 'FrontEnd'; // bad const item = { job: job, }; // good const item = { job, }; ``` * 对象属性值的简写方式要和声明式的方式分组 ``` js const job = 'FrontEnd'; const department = 'JDC'; // bad const item = { sex: 'male', job, age: 25, department, }; // good const item = { job, department, sex: 'male', age: 25, }; ``` #### 数组 * 请使用字面量值创建数组 ``` js // bad const items = new Array(); // good const items = []; ``` * 向数组中添加元素时,请使用 `push` 方法 ``` js const items = []; // bad items[items.length] = 'test'; // good items.push('test'); ``` * 使用拓展运算符 `...` 复制数组 ``` js // bad const items = []; const itemsCopy = []; const len = items.length; let i; // bad for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good itemsCopy = [...items]; ``` * 使用数组的 `map` 等方法时,请使用 `return` 声明,如果是单一声明语句的情况,可省略 `return` ``` js // good [1, 2, 3] .map((x) => { const y = x + 1; return x * y; }) [ // good (1, 2, 3) ].map((x) => x + 1); // bad const flat = {} [([0, 1], [2, 3], [4, 5])].reduce((memo, item, index) => { const flatten = memo.concat(item); flat[index] = flatten; }); // good const flat = {} [([0, 1], [2, 3], [4, 5])].reduce((memo, item, index) => { const flatten = memo.concat(item); flat[index] = flatten; return flatten; }); // bad inbox.filter((msg) => { const { subject, author } = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } else { return false; } }); // good inbox.filter((msg) => { const { subject, author } = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } return false; }); ``` #### 解构赋值 * 当需要使用对象的多个属性时,请使用解构赋值 ``` js // bad function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}` ; } // good function getFullName(user) { const { firstName, lastName } = user; return `${firstName} ${lastName}` ; } // better function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}` ; } ``` * 当需要使用数组的多个值时,请同样使用解构赋值 ``` js const arr = [1, 2, 3, 4]; // bad const first = arr[0]; const second = arr[1]; // good const [first, second] = arr; ``` * 函数需要回传多个值时,请使用对象的解构,而不是数组的解构 ``` js // bad function doSomething() { return [top, right, bottom, left]; } // 如果是数组解构,那么在调用时就需要考虑数据的顺序 const [top, xx, xxx, left] = doSomething(); // good function doSomething() { return { top, right, bottom, left }; } // 此时不需要考虑数据的顺序 const { top, left } = doSomething(); ``` #### 字符串 * 字符串统一使用单引号的形式 `''` ``` js // bad const department = 'JDC'; // good const department = 'JDC'; ``` * 字符串太长的时候,请不要使用字符串连接符换行 `\` ,而是使用 `+` ``` js const str = '字符串太长 字符串太长 字符串太长' + '字符串太长 字符串太长 字符串太长' + '字符串太长 字符串太长'; ``` * 程序化生成字符串时,请使用模板字符串 ``` js const test = 'test'; // bad const str = ['a', 'b', test].join(); // bad const str = 'a' + 'b' + test; // good const str = `ab${test}` ; ``` #### 函数 * 请使用函数声明,而不是函数表达式 ``` js // bad const foo = function() { // do something }; // good function foo() { // do something } ``` * 不要在非函数代码块中声明函数 ``` js // bad if (isUse) { function test() { // do something } } // good let test; if (isUse) { test = () => { // do something }; } ``` * 不要使用 `arguments` ,可以选择使用 `...` > `arguments` 只是一个类数组,而 `...` 是一个真正的数组 ``` js // bad function test() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // good function test(...args) { return args.join(''); } ``` * 不要更改函数参数的值 ``` js // bad function test(opts) { opts = opts || {}; } // good function test(opts = {}) { // ... } ``` #### 原型 * 使用 `class` ,避免直接操作 `prototype` ``` js // bad function Queue(contents = []) { this._queue = [..contents] } Queue.prototype.pop = function() { const value = this._queue[0] this._queue.splice(0, 1) return value } // good class Queue { constructor(contents = []) { this._queue = [...contents] } pop() { const value = this._queue[0] this._queue.splice(0, 1) return value } } ``` #### 模块 * 使用标准的 ES6 模块语法 `import` 和 `export` ``` js // bad const util = require('./util'); module.exports = util; // good import Util from './util'; export default Util; // better import { Util } from './util'; export default Util; ``` * 不要使用 `import` 的通配符 `*` ,这样可以确保你只有一个默认的 export ``` js // bad import * as Util from './util'; // good import Util from './util'; ``` #### 迭代器 * 不要使用 `iterators` ``` js const numbers = [1, 2, 3, 4, 5]; // bad let sum = 0; for (let num of numbers) { sum += num; } // good let sum = 0; numbers.forEach((num) => (sum += num)); // better const sum = numbers.reduce((total, num) => total + num, 0); ``` #### 对象属性 * 使用 `.` 来访问对象属性 ``` js const joke = { name: 'haha', age: 28, }; // bad const name = joke['name']; // good const name = joke.name; ``` #### 变量声明 * 声明变量时,请使用 `const` 、 `let` 关键字,如果没有写关键字,变量就会暴露在全局上下文中,这样很可能会和现有变量冲突,另外,也很难明确该变量的作用域是什么。这里推荐使用 `const` 来声明变量,我们需要避免全局命名空间的污染。 ``` js // bad demo = new Demo(); // good const demo = new Demo(); ``` * 将所有的 `const` 和 `let` 分组 ``` js // bad let a const b let c const d let e // good const b const d let a let c let e ``` #### 变量提升 * `var` 存在变量提升的情况,即 `var` 声明会被提升至该作用域的顶部,但是他们的赋值并不会。而 `const` 和 `let` 并不存在这种情况,他们被赋予了 [Temporal Dead Zones, TDZ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone_and_errors_with_let) ``` js function example() { console.log(notDefined); // => throws a ReferenceError } function example() { console.log(declareButNotAssigned); // => undefined var declaredButNotAssigned = true; } function example() { let declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; } function example() { console.log(declaredButNotAssigned); // => throws a ReferenceError console.log(typeof declaredButNotAssigned); // => throws a ReferenceError const declaredButNotAssigned = true; } ``` * 匿名函数的变量名会提升,但函数内容不会 ``` js function example() { console.log(anonymous); // => undefined anonymous(); var anonymous = function() { console.log('test'); }; } ``` * 命名的函数表达式的变量名会被提升,但函数名和函数函数内容并不会 ``` js function example() { console.log(named); // => undefined named(); // => TypeError named is not a function superPower(); // => ReferenceError superPower is not defined var named = function superPower() { console.log('Flying'); }; } function example() { console.log(named); // => undefined named(); // => TypeError named is not a function var named = function named() { console.log('named'); }; } ``` #### 比较和相等 * 使用 `===` 和 `!==` ,而不是 `==` 和 `!=` * 布尔值比较可以省略,但是字符串和数字要显示比较 ``` js // bad if (isValid === true) { // ... } // good if (isValid) { // ... } // bad if (name) { // ... } // good if (name !== '') { // ... } // bad if (collection.length) { // ... } // good if (collection.length > 0) { // ... } ``` #### 分号 * 我们遵循 `Standard` 的规范,不使用分号。 > 关于应不应该使用分号的讨论有很多,本规范认为非必要的时候,应该不使用分号。 ``` js // bad const test = 'good'; (function() { const str = 'hahaha' })() // good const test = 'good'; (() => { const str = 'hahaha' })(); ``` #### 标准特性 为了代码的可移植性和兼容性,我们应该最大化的使用标准方法,例如优先使用 `string.charAt(3)` 而不是 `string[3]` #### eval() 由于 `eval` 方法比较 `evil` ,所以我们约定禁止使用该方法 #### with() {} 由于 `with` 方法会产生神奇的作用域,所以我们也是禁止使用该方法的 #### for-in 循环 推荐使用 `for in` 语法,但是在对对象进行操作时,容易忘了检测 `hasOwnProperty(key)` ,所以我们约定启用 `ESLint` 的 `guard-for-in` 选项 > 对数组进行 `for in` 的时候,顺序是不固定的 #### 修改内置对象的原型 不要修改内置对象,如 `Object` 和 `Array` --- ### 编码规范 统一团队的编码规范,有助于代码的维护。目的是统一一些相对主观化的代码风格。 #### 单行代码块 在单行代码块中使用空格 _不推荐_ ``` function foo () {return true} if (foo) {bar = 0} ``` _推荐_ ``` function foo () { return true } if (foo) { bar = 0 } ``` #### 大括号风格 在编程过程中,大括号风格与缩进风格紧密联系,用来描述大括号相对代码块位置的方法有很多。在 JavaScript 中,主要有三种风格,如下: * **One True Brace Style** ``` if (foo) { bar() } else { baz() } ``` * **Stroustrup** ``` if (foo) { bar() } else { baz() } ``` * **Allman** ``` if (foo) { bar() } else { baz() } ``` 我们约定使用 `One True Brace Style` 风格 #### 变量命名 当命名变量时,主流分为驼峰式命名(variableName)和下划线命名(variable_name)两大阵营。 > 团队约定使用驼峰式命名 #### 拖尾逗号 在 ECMAScript5 里面,对象字面量中的拖尾逗号是合法的,但在 IE8(非 IE8 文档模式)下,当出现拖尾逗号,则会抛出错误。 拖尾逗号的例子: ``` js var foo = { name: 'foo', age: '22', }; ``` 拖尾逗号的好处是,简化了对象和数组添加或删除元素,我们只需要修改新增的行即可,并不会增加差异化的代码行数。 > 因为拖尾逗号有好也有不好,所以团队约定允许在最后一个元素或属性与闭括号 `]` 或 `}` 在不同行时,可以(但不要求)使用拖尾逗号。当在同一行时,禁止使用拖尾逗号。 #### 逗号空格 逗号前后的空格可以提高代码的可读性,团队约定在逗号后面使用空格,逗号前面不加空格。 _不推荐_ ``` var foo = 1,bar = 2 var foo = 1 , bar = 2 var foo = 1 ,bar = 2 ``` _推荐_ ``` var foo = 1, bar = 2 ``` #### 逗号风格 逗号分隔列表时,在 JavaScript 中主要有两种逗号风格: * 标准风格,逗号放置在当前行的末尾 * 逗号前置风格,逗号放置在下一行的开始位置 > 团队约定使用标准风格 _不推荐_ ``` var foo = 1 , bar = 2 var foo = 1 , bar = 2 var foo = ['name' , 'age'] ``` _推荐_ ``` js var foo = 1, bar = 2 var foo = ['name', 'age']; ``` #### 计算属性的空格 团队约定在对象的计算属性内,禁止使用空格 _不推荐_ ``` obj['foo' ] obj[ 'foo'] obj[ 'foo' ] ``` _推荐_ ``` js obj['foo'] ``` #### 拖尾换行 在非空文件中,存在拖尾换行是一个常见的 `UNIX` 风格,它的好处是可以方便在串联和追加文件时不会打断 `Shell` 的提示。在日常的项目中,保留拖尾换行的好处是,可以减少版本控制时的代码冲突。 _不推荐_ ``` js function func() { // do something } ``` _推荐_ ``` js function func() { // do something } // 此处是新的一行 ``` > 可以通过 .editorconfig 添加 EOL #### 函数调用 为了避免语法错误,团队约定在函数调用时,禁止使用空格 _不推荐_ ``` fn () fn () ``` _推荐_ ``` js fn() ``` #### 缩进 代码保持一致的缩进,是作为工程师的职业素养。但缩进用两个空格,还是四个空格,是用 `Tab` 还是空格呢?这样的争论太多了,也得不出答案。本规范结合了市面上优秀的开源项目,姑且约定使用 `空格` 来缩进,而且缩进使用两个空格。 那是不是不能使用 `Tab` 进行缩进了?我们可以通过配置 `.editorconfig` ,将 `Tab` 自动转换为空格。 #### 对象字面量的键值缩进 团队约定对象字面量的键和值之间不能存在空格,且要求对象字面量的冒号和值之间存在一个空格 _不推荐_ ``` var obj = { 'foo' : 'haha' } ``` _推荐_ ``` var obj = { 'foo': 'haha' } ``` #### 构造函数首字母大写 在 JavaScript 中 `new` 操作符用来创建某个特定类型的对象的一个实例,该类型的对象是由一个构造函数表示的。由于构造函数只是常规函数,唯一区别是使用 `new` 来调用。所以我们团队约定构造函数的首字母要大小,以此来区分构造函数和普通函数。 _不推荐_ ``` js var fooItem = new foo() ``` _推荐_ ``` js var fooItem = new Foo() ``` #### 构造函数的参数 在 JavaScript 中,通过 `new` 调用构造函数时,如果不带参数,可以省略后面的圆括号。但这样会造成与整体的代码风格不一致,所以团队约定使用圆括号 _不推荐_ ``` var person = new Person ``` _推荐_ ``` js var person = new Person() ``` #### 链式调用 链式调用如果放在同一行,往往会造成代码的可读性差,但有些时候,短的链式调用并不会影响美观。所以本规范约定一行最多只能有四个链式调用,超过就要求换行。 #### 空行 空白行对于分离代码逻辑有帮助,但过多的空行会占据屏幕的空间,影响可读性。团队约定最大连续空行数为 2 _不推荐_ ``` var a = 1 var b = 2 ``` _推荐_ ``` js var a = 1 var b = 2 ``` #### 链式赋值 链式赋值容易造成代码的可读性差,所以团队约定禁止使用链式赋值 _不推荐_ ``` js var a = (b = c = 1) ``` _推荐_ ``` js var a = 1 var b = 1 var c = 1 ``` #### 变量声明 JavaScript 允许在一个声明中,声明多个变量。团队约定在声明变量时,一个声明只能有一个变量 _不推荐_ ``` js var a, b, c ``` _推荐_ ``` js var a var b var c ``` #### 分号 JavaScript 在所有类 C 语言中是比较独特的,它不需要在每个语句的末尾有分号。在很多情况下,JavaScript 引擎可以确定一个分号应该在什么位置然后自动添加它。此特征被称为 自动分号插入 (ASI),被认为是 JavaScript 中较为有争议的特征。 团队中对于是否应该使用分号,也有许多争论,本规范不推荐使用分号,因为我们认为好的工程师应该知道什么时候该加,什么时候不该加。 相关参考 :[semi](http://eslint.org/docs/rules/semi) #### 代码块空格 一致性是任何风格指南的重要组成部分。虽然在哪里放置块的开括号纯属个人偏好,但在整个项目中应该保持一致。不一致的风格将会分散读者阅读代码的注意力。 > 团队约定代码块前要添加空格 _不推荐_ ``` if (a) { b() } function a(){} ``` _推荐_ ``` js if (a) { b() } function a() {} ``` #### 函数声明的空格 当格式化一个函数,函数名或 function 关键字与左括号之间允许有空白。命名函数要求函数名和 function 关键字之间有空格,但是匿名函数要求不加空格。 > 团队约定函数括号前不要加空格 _不推荐_ ``` function func (x) { // ... } ``` _推荐_ ``` js function func(x) { // ... } ``` #### 操作符的空格 团队约定操作符前后都需要添加空格 _不推荐_ ``` var sum = 1+2 ``` _推荐_ ``` js var sum = 1 + 2 ``` ## 开发约定 > 使用vscode + eslint + prettier 实现团队代码风格统一 ### 主要工具有: * .vscode/settings.json 项目关联的vscode配置; * editorconfig 主要负责代码风格(行尾结束符、缩进风格等)统一; * eslint 主要负责代码质量校验及代码格式校验 * prettier 主要负责代码格式化 ## git commit规范 > 约定基于Angular commit message规范的简化版本,暂拟订如下格式的commit规范: ``` (): //<类型>(影响的范围):<简要描述> ``` ### type:commit类型 > type类型只能从以下7种类型中,结合实际情况选取 + feat: 新特性 + fix: 修复问题 + refactor: 代码重构 + docs: 文档修改 + style: 代码格式修改,注意不是css修改 + chore: 其它修改,比如构建流程,依赖管理 + revert:revert前一个commit ### scope:commit影响的范围 >比如:route,component,utils,build ### subject:commit的概述 >本次提交的简短描述,以动词开头 ### 其它注意事项 >建议一次提交只涉及一个模块,如果实在涉及多个模块,建议拆分成多次提交或者编写多行符合上述规范的 message ### commit Demo ``` feat(baseURL.js): 增加演示环境配置 fix(request.js): 屏蔽公参中的token feat(购物车模块): 增加清空购物车功能 ```