1. 目的
统一团队编码风格,汇集团队最佳编码实践经验,增强代码可读性和可维护性,进而提高团队协作和开发效率以及代码质量。
2. 原则
- ✅ 符合 W3C 标准
- ✅ 语义化,结构、表现、行为分离
- ✅ 代码质量、性能和兼容性优良
3. 公共规范
3.1 目录和文件命名
- 【强制】目录和文件名不能以数字开头,语义化命名
- 【强制】非特殊情况,目录和文件名默认采用 kebab-case 方式,即以全小写字母加
-连接(新项目强制执行,旧项目根据情况尽量遵守) - 内容有复数结构时,采用复数形式命名,如
utils、styles
3.2 代码格式
- 【强制】缩进使用 2 个空格或软 tab 设置为 2 个空格
- 代码片段、变量和符号间留适当空格
3.3 文件编码
- 【强制】使用无 BOM 的 UTF-8 编码
3.4 外联资源引入
- 【强制】站内外联资源用相对路径引入
- 【强制】站外外联资源用 https 协议的全路径引入
4. HTML 规范
-
【强制】按语义化使用标签,如:
header、footer -
【强制】标签嵌套规范
- 内联元素不要包含块级元素
p标签不要包含块级元素a标签非特殊情况避免嵌套
-
【强制】
img、input、br等标签不需要闭合 -
【强制】减少不必要的标签数量,避免过度嵌套
-
【强制】同一元素类名不超过 5 个
-
尽量避免在元素上写
style -
重要图片必须加上
alt属性 -
给重要的元素和截断的元素加上
title -
html加上lang属性 -
HTML 模板加上声明:
html<!DOCTYPE html> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> -
HTML 标签分类参考: html标签分类
5. CSS 规范
5.1 命名规范
- 【强制】命名规范:
- 由小写字母、
-、数字组成 - 语义化命名
- 模块化前缀:
全局(系统名,非必要)-模块(模块名)-组件 - 举例:
fbs-inbound-request-dialog
- 由小写字母、
5.2 词汇规范
- 推荐根据内容、功能来命名,不依据表现形式来命名
- ✅ 推荐:
nav、aside、news、type、search - ❌ 不推荐:
left、right、top### 5.3 属性顺序
- ✅ 推荐:
-
Position
cssposition: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 100; -
Box model
cssdisplay: block; float: right; width: 100px; height: 100px; -
Typographic
cssfont: normal 13px "Helvetica Neue", sans-serif; line-height: 1.5; color: #333; text-align: center; -
Visual
cssbackground-color: #f5f5f5; border: 1px solid #e5e5e5; border-radius: 3px; -
Misc
cssopacity: 1;
5.4 其他规范
- 超过 2 个同类属性使用缩写,比如:
margin、padding、font等 0不带单位,除非是deg等特殊单位- 小数不带
0
5.5 布局特性
充分了解并使用布局特性,减少不必要或无效的属性声明:
display: inline后不应该再使用width、height、margin上下、padding以及floatdisplay: inline-block后不应该再使用floatdisplay: block后不应该再使用vertical-aligndisplay: table-*后不应该再使用margin或者float- 合理使用 BFC 来解决 margin 重叠、清除浮动等
5.6 性能优化
- 减少不必要的嵌套,不超过 3 级嵌套
- 选择器使用优先级(CSS 树是从下往上,选择器从右往左匹配):
- 类选择器(
.myclassname) - 标签选择器(
div、h1、p) - 相邻选择器(
h1+p) - 子选择器(
ul > li) - 后代选择器(
li a) - 通配符选择器(
*) - 属性选择器(
a[rel="external"]) - 伪类选择器(
a:hover、li:nth-child)
- 类选择器(
- 【强制】禁止
id选择器用于样式声明 - 尽量使用属性继承:
- 字体系列:
font a标签字体颜色不能被继承- 文本系列:
text-align、line-height、color等 - table 属性:
caption-side、border-collapse、empty-cells - list 属性:
list-style
- 字体系列:
- 尽量避免使用高性能消耗的 CSS 属性:
gradientfilterbox-shadow!important
- 尽量避免重排重绘
6. JS 规范
6.1 命名规范
- 【强制】命名规范:
- 变量名使用小驼峰命名,首字母小写
- 类名采用驼峰命名法,首字母大写
- 常量采用蛇形命名法,大写加
_分割 - 与后台对接字段可遵循后台规范,使用全小写加
_分割,减少不必要的转换 boolean类型的变量使用is、has、can开头
- 【推荐】拼写能够表明含义,除了业界常用名词外使用英文拼写
6.2 代码格式
- 【强制】语句结束必须加分号
- 【强制】使用 TypeScript 进行开发
6.3 注释规范
- 适当的注释:特殊业务、复杂逻辑等写明处理
- 注释建议英文,可以使用中文
- 函数内使用单行注释,多行时可使用多个单行
// - 文档注释参考规范:JSDoc
- 尽量使用单行注释或多个单行注释
- 建议使用
TODO
6.4 函数规范
- 【建议】长度标准:小于 50 行,复杂功能尽量抽出来
- 最小函数准则,职责单一
- 参数标准:小于 4,超出尽量使用
options - 函数命名需要语义化
- ✅ 推荐:
getClientID - ❌ 不推荐:
idFun
- ✅ 推荐:
6.5 变量规范
- 变量声明放置顶端,在 JS 中即使放置于中间也会被提前
- 【强制】禁止使用
var,如有必要全局变量可用window.xxx声明 - 使用明确的类型赋值和判断,比如使用
!!、true/false、===、isArray等 - 【强制】不要扩充内置或第三方原型,比如:
Array、String等
6.6 性能优化
- 避免不必要的 DOM 查询或操作次数,可以缓存变量
- 如有必要尽量使用
id作为 JS 选择器
6.7 异常处理
- 【强制】所有的异常情况都需要处理
await需使用try catch捕获异常,按需抛出新的Error- 避免内存泄漏
6.8 其他规范
- 不要使用魔法数字
- 不相信任何外部输入,必须做容错判断
- 自测必须覆盖每一行代码,每一个逻辑分支
- 中途变更实现后,必须重新确认全部 checklist
- 提交前必须检查代码:整理代码思路是否清晰,去除调试代码
- 所有代码都应该有功能边界,职责明确
- 组件和模块间交互输入输出明确且收敛,避免依赖发散,如:减少
$refs操作,避免store直接修改等 - 【建议】代码重复不超过 2 遍
- 函数或者后台接口输入输出保持最少字段原则
6.9 模块引入顺序
模块引入顺序应如:
- 外部模块
- 空行
- 内部模块
- 空行
- 外部组件
- 空行
- 内部组件
- 空行
- CSS 相关
7. 框架使用规范
7.1 Vue
7.1.1 Vue 项目文件目录及命名
api # 所有后台接口声明
assets # 所有icon、图片等可能打包到代码的静态资源
static # 所有图片、文件等不需要打包的静态资源
styles # 公共样式
components # 公共组件
router # 路由
lang # 国际化翻译
utils # 公共工具类或函数
views # 页面,对应路由
store # 公共仓库
types # TS类型声明
7.1.2 Vue 编码规范
- 除了计算属性以外避免内联样式,动态切换可通过切换 Class 实现,比如枚举状态
- 【强制】所有属性名称都使用小写字母加
-方式,Vue 官方建议小写,因为 HTML 大小写不敏感,可能导致一些冲突问题隐患 - 【强制】Vue 使用
props时,需声明类型,且子组件禁止直接修改,如有需要可用v-model方式来简化调用方式 - 【强制】双向绑定的字段需要初始化定义,否则后续需使用
$set添加属性 - 【强制】写操作一定要加
loading防重复点击 - 避免在
template写过于复杂的计算逻辑,应该在method或者computed中使用 - 【强制】禁止在
computed属性中修改data - 合理抽取组件、函数等提高代码复用性,建议代码行数 200-300 行,最大不得超过 500 行,超过 500 行的需注明原因
- 尽量使用
v-if,如果遇频繁操作可使用v-show
7.1.3 组件属性顺序
namecomponents/directives/filtersextends/mixinsmodel/props/propsDatadata/computedwatch/ 生命周期钩子methods
7.1.4 模板属性顺序
isv-for/v-if/v-else-if/v-else/v-show/v-cloakv-pre/v-onceidref/key/slot- 使用缩写
:,不建议v-bind v-model- 使用缩写
@,不建议v-on v-html/v-text
7.1.5 其他注意事项
- 组件当中有绑定原生事件或定时器,在组件注销前进行移除
- 参考:Vue 风格指南
7.2 React
7.2.1 React 项目文件夹分类
api # 所有后台接口声明
assets # 所有icon、图片、文件等可能打包到代码的静态资源
static # 所有图片、文件等不需要打包静态资源
styles # 公共样式
components # 公共组件、公共容器
router # 路由
lang # 国际化
utils # 公共工具类或函数
views # 页面,对应路由
redux # 公共仓库
types # TS类型声明
7.2.2 React 编码规范
- 尽量使用函数组件,推荐使用 React Hooks
- 【强制】对于不影响 UI 更新的状态,使用
useRef而非useState - 【强制】所有 hooks 的定义必须在组件的第一层,禁止在
if、for、闭包中定义 hooks - 【强制】需要开启 ESLint 的
react-hooks校验,若遇到useEffect空依赖报错,在确定只需要执行一次时,使用// eslint-disable-line react-hooks/exhaustive-deps - 【强制】避免在 class 组件的
render函数(或函数式组件)内部创建新的闭包 - 不要使用数组的索引作为
key值 - 在专用组件中渲染列表
- 当
render过于复杂时,应该拆分成若干组件 - 遵循单一职责原则,使用 HOC / 装饰器 / Render Props 增加职责
- 【强制】定义组件时,使用
interface来代替prop-types包 - 把
state往上层组件提取,让下层组件只需要实现为纯函数 - 使用
setState修改状态,但尽量合并操作,减少调用频次 - 参考:React 性能优化
8. 图片规范
- 【强制】图片需设置默认图片,添加
onerror处理 - 【强制】网站配置默认
favicon.ico文件 - 【强制】
img的src禁止为空,延迟加载也需要给默认图 - 单张图片 PC 端小于 100KB,移动端小于 50KB
- 质量标准为 65(肉眼辨别临界值),高质量为 80(用于下载)
- 使用 SVG,图标去除颜色,由 CSS 控制颜色
9. 规范检测
ESLint / TSLint 详见配置文件
typescript
{
extends: [
// 公共部分
'plugin:import/errors', // https://www.npmjs.com/package/eslint-plugin-import
'plugin:import/warnings',
'plugin:@typescript-eslint/eslint-recommended', // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/eslint-recommended.ts
'plugin:@typescript-eslint/recommended', // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/recommended.ts
// react项目
'plugin:react/recommended', // https://github.com/yannickcr/eslint-plugin-react#Recommended
// vue项目
'plugin:vue/essential', // https://eslint.vuejs.org/rules/no-arrow-functions-in-watch.html
'plugin:vue/vue3-essential', // https://eslint.vuejs.org/rules/no-deprecated-data-object-declaration.html
],
plugins: ['@typescript-eslint', 'import', 'react'],
// ES部分
rules: {
// 0-off, 1-warning, 2-error
'max-len': [2, { 'code': 120, 'ignoreComments': true, 'ignoreTrailingComments': true, 'ignoreUrls': true}], // 每行长度最大120,忽略注释和url
'accessor-pairs': 2, // 强制 getter 和 setter 在对象中成对出现
'arrow-spacing': [2, { 'before': true, 'after': true }], // 强制箭头函数的箭头前后使用一致的空格
'block-spacing': [2, 'always'], // 强制在代码块中开括号前和闭括号后有空格
'brace-style': [2, '1tbs', { 'allowSingleLine': true }], // 强制在代码块中使用一致的大括号风格
'camelcase': [0, { 'properties': 'always' }], // 不强制使用骆驼拼写法命名约定
'comma-dangle': [2, 'always-multiline'], // 多行时要求末尾逗号
'comma-spacing': [2, { 'before': false, 'after': true }], // 强制在逗号前后使用一致的空格
'comma-style': [2, 'last'], // 强制使用一致的逗号风格
'constructor-super': 2, // 要求在构造函数中有 super() 的调用
'curly': 0, // 强制所有控制语句使用一致的括号风格
'dot-location': [2, 'property'], // 强制在点号之前和之后一致的换行
'eol-last': 2, // 要求文件末尾存在空行
'eqeqeq': 2, // 要求使用 === 和 !==
'generator-star-spacing': [2, { 'before': true, 'after': true }], // 强制 generator 函数中 * 号周围使用一致的空格
'handle-callback-err': [2, '^(err|error)$'], // 要求回调函数中有容错处理
'indent': [2, 2, { 'SwitchCase': 1 }], // 强制使用一致的缩进
'jsx-quotes': [2, 'prefer-double'], // 强制在 JSX 属性中一致地使用双引号
'key-spacing': [2, { 'beforeColon': false, 'afterColon': true }], // 强制在对象字面量的属性中键和值之间使用一致的间距
'keyword-spacing': [2, { 'before': true, 'after': true }], // 强制在关键字前后使用一致的空格
'new-cap': [2, { 'newIsCap': true, 'capIsNew': false }], // 要求构造函数首字母大写
'new-parens': 2, // 强制调用无参构造函数时有圆括号
'no-array-constructor': 2, // 禁用 Array 构造函数
'no-caller': 2, // 禁用 arguments.caller 或 arguments.callee
'no-console': 2, // 禁用 console
'no-class-assign': 2, // 禁止修改类声明的变量
'no-cond-assign': 2, // 禁止条件表达式中出现赋值操作符
'no-const-assign': 2, // 禁止修改 const 声明的变量
'no-control-regex': 2, // 禁止在正则表达式中使用控制字符
'no-delete-var': 2, // 禁止删除变量
'no-dupe-args': 2, // 禁止 function 定义中出现重名参数
'no-dupe-class-members': 2, // 禁止类成员中出现重复的名称
'no-dupe-keys': 2, // 禁止对象字面量中出现重复的 key
'no-duplicate-case': 2, // 禁止出现重复的 case 标签
'no-empty-character-class': 2, // 禁止在正则表达式中使用空字符集
'no-empty-pattern': 2, // 禁止使用空解构模式
'no-eval': 2, // 禁用 eval()
'no-ex-assign': 2, // 禁止对 catch 子句的参数重新赋值
'no-extend-native': 2, // 禁止扩展原生类型
'no-extra-bind': 2, // 禁止不必要的 .bind() 调用
'no-extra-boolean-cast': 2, // 禁止不必要的布尔转换
'no-extra-parens': [2, 'functions'], // 禁止不必要的括号
'no-fallthrough': 2, // 禁止 case 语句落空
'no-floating-decimal': 2, // 禁止数字字面量中使用前导和末尾小数点
'no-func-assign': 2, // 禁止对 function 声明重新赋值
'no-implied-eval': 2, // 禁止使用类似 eval() 的方法
'no-inner-declarations': [2, 'functions'], // 禁止在嵌套的块中出现变量声明或 function 声明
'no-invalid-regexp': 2, // 禁止 RegExp 构造函数中存在无效的正则表达式字符串
'no-irregular-whitespace': 2, // 禁止不规则的空白
'no-iterator': 2, // 禁用 __iterator__ 属性
'no-label-var': 2, // 不允许标签与变量同名
'no-labels': [2, { 'allowLoop': false, 'allowSwitch': false }], // 禁用标签语句
'no-lone-blocks': 2, // 禁用不必要的嵌套块
'no-mixed-spaces-and-tabs': 2, // 禁止空格和 tab 的混合缩进
'no-multi-spaces': 2, // 禁止使用多个空格
'no-multi-str': 2, // 禁止使用多行字符串
'no-multiple-empty-lines': [2, { 'max': 1 }], // 禁止出现多行空行
'no-new-object': 2, // 禁用 Object 的构造函数
'no-new-require': 2, // 禁止调用 require 时使用 new 操作符
'no-new-symbol': 2, // 禁止 Symbolnew 操作符和 new 一起使用
'no-new-wrappers': 2, // 禁止对 String,Number 和 Boolean 使用 new 操作符
'no-obj-calls': 2, // 禁止把全局对象作为函数调用
'no-octal': 2, // 禁用八进制字面量
'no-octal-escape': 2, // 禁止在字符串中使用八进制转义序列
'no-path-concat': 2, // 禁止对 __dirname 和 __filename 进行字符串连接
'no-proto': 2, // 禁用 __proto__ 属性
'no-redeclare': 2, // 禁止多次声明同一变量
'no-regex-spaces': 2, // 禁止正则表达式字面量中出现多个空格
'no-return-assign': [2, 'except-parens'], // 禁止在 return 语句中使用赋值语句
'no-self-assign': 2, // 禁止自我赋值
'no-self-compare': 2, // 禁止自身比较
'no-sequences': 2, // 禁用逗号操作符
'no-shadow-restricted-names': 2, // 禁止将标识符定义为受限的名字
'no-sparse-arrays': 2, // 禁用稀疏数组
'no-this-before-super': 2, // 禁止在构造函数中,在调用 super() 之前使用 this 或 super
'no-throw-literal': 2, // 禁止抛出异常字面量
'no-trailing-spaces': 2, // 禁用行尾空格
'no-undef': 2, // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到 'no-undef-init': 2, // 禁止将变量初始化为 undefined
'no-unexpected-multiline': 2, // 禁止出现令人困惑的多行表达式
'no-unmodified-loop-condition': 2, // 禁用一成不变的循环条件
'no-unneeded-ternary': [2, { 'defaultAssignment': false }], // 禁止可以在有更简单的可替代的表达式时使用三元操作符
'no-unreachable': 2, // 禁止在 return、throw、continue 和 break 语句之后出现不可达代码
'no-unsafe-finally': 2, // 禁止在 finally 语句块中出现控制流语句
'no-unused-vars': [2, { 'vars': 'all', 'args': 'none' }], // 禁止出现未使用过的变量
'no-useless-call': 2, // 禁止不必要的 .call() 和 .apply()
'no-useless-computed-key': 2, // 禁止在对象中使用不必要的计算属性
'no-useless-constructor': 2, // 禁用不必要的构造函数
'no-useless-escape': 0, // 禁用不必要的转义字符
'no-whitespace-before-property': 2, // 禁止属性前有空白
'no-with': 2, // 禁用 with 语句
'one-var': [2, { 'initialized': 'never' }], // 强制函数中的变量要么一起声明要么分开声明
'operator-linebreak': [2, 'after', { 'overrides': { '?': 'before', ':': 'before' }}], // 强制操作符使用一致的换行符
'padded-blocks': [2, 'never'], // 禁止块内填充
'quotes': [2, 'single', { 'avoidEscape': true, 'allowTemplateLiterals': true }], // 强制使用一致的反勾号、双引号或单引号
'semi': [2, 'always'], // 要求使用分号代替 ASI
'semi-spacing': [2, { 'before': false, 'after': true }], // 强制分号之前和之后使用一致的空格
'space-before-blocks': [2, 'always'], // 强制在块之前使用一致的空格
'space-before-function-paren': [2, 'never'], // 强制在 function的左括号之前使用一致的空格
'space-in-parens': [2, 'never'], // 强制在圆括号内使用一致的空格
'space-infix-ops': 2, // 要求操作符周围有空格
'space-unary-ops': [2, { 'words': true, 'nonwords': false }], // 强制在一元操作符前后使用一致的空格
'spaced-comment': [2, 'always', { 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] }], // 强制在注释中 // 或 /* 使用一致的空格
'template-curly-spacing': [2, 'never'], // 禁止模板字符串中的嵌入表达式周围空格的使用
'use-isnan': 2, // 要求使用 isNaN() 检查 NaN
'valid-typeof': 2, // 强制 typeof 表达式与有效的字符串进行比较
'wrap-iife': [2, 'any'], // 要求 IIFE 使用括号括起来
'yield-star-spacing': [2, 'both'], // 强制在 yield* 表达式中 * 周围使用空格
'yoda': [2, 'never'], // 禁止 "Yoda" 条件
'prefer-const': 2, // 要求使用 const 声明那些声明后不再被修改的变量
'no-debugger': 2, // 禁用 debugger
'object-curly-spacing': [2, 'always', { 'objectsInObjects': true }], // 强制在大括号中使用一致的空格
'array-bracket-spacing': [2, 'never'], // 强制数组方括号中使用一致的空格'
// eslint-plugin-import 相关
'import/no-unresolved': 2, // 禁止从无法匹配的路径中import依赖(路径区分大小写)
'import/default': 2, // 禁止从没有默认导出的模块中请求默认导入
'import/no-absolute-path': 2, // 禁止从绝对路径中导入
'import/no-self-import': 2, // 禁止模块导入自己
'import/no-duplicates': 2, // 禁止多次从同一个模块中导入
'import/order': [2, {'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object']}], // 规范导入顺序, https://github.com/benmosher/eslint-plugin-import/blob/HEAD/docs/rules/order.md#importorder-enforce-a-convention-in-module-import-order
'import/export': 2, // 禁止无效导出
}
// React部分
rules: {
// eslint-plugin-react 相关
'react/jsx-boolean-value': 'never', // 布尔值的prop值为true时使用简写
'react/jsx-closing-bracket-location': 2, // 正确关闭组件标签
'react/display-name': 0, // 必须设置display name
'react/jsx-equals-spacing': 2, // 强制等号周围存在空格
'react/jsx-filename-extension': [2, {'extensions': ['.jsx', '.tsx']}], // react组件的文件名后缀强制为jsx或tsx
'react/jsx-handler-names': 'off', // 统一事件handler的命名,可讨论
'react/jsx-indent-props': [2, 2], // prop前缩进为2
'react/jsx-indent': [2, 2], // 缩进为2
'react/jsx-key': 2, // 循环渲染的组件必须有key
'react/jsx-no-bind': [2, {'ignoreRefs': true}], // 禁止prop使用Function.prototype.bind和箭头函数,但忽略ref
'react/jsx-no-duplicate-props': 2, // 禁止重复prop
'react/jsx-no-literals': 0, // 禁止在JSX中使用字符串文字
'react/jsx-no-target-blank': 2, // 禁止target="_blank"的a标签不设置rel="noreferrer"
'react/jsx-no-undef': 2, // 禁止使用未定义的变量
'react/jsx-pascal-case': 2, // 组件名必须使用pascal case
'react/jsx-sort-props': 0, // prop按字典序排序
'react/jsx-tag-spacing': 2, // 校验JSX开闭标签周围的空格
'react/jsx-uses-react': 0, // 防止React被错误地标记为未使用
'react/jsx-uses-vars': 2, // 防止将JSX中使用的变量错误地标记为未使用
'react/no-array-index-key': 2, // 禁止使用数组的index作为组件的key
'react/no-children-prop': 2, // 禁止将prop命名为children
'react/no-danger': 1, // 防止使用危险的jsx属性
'react/no-deprecated': 2, // 禁止使用deprecated的方法
'react/no-did-mount-set-state': 0, // 禁止在didMount时setState
'react/no-did-update-set-state': 2, // 禁止在didUpdate时setState
'react/no-will-update-set-state': 2, // 禁止在willUpdate时setState
'react/no-direct-mutation-state': 2, // 禁止对this.state直接赋值
'react/no-find-dom-node': 2, // 禁止使用findDOMNode
'react/no-is-mounted': 2, // 禁止使用isMounted
'react/no-multi-comp': [2, {'ignoreStateless': true}], // 禁止在一个文件中定义多个class组件
'react/no-set-state': 0, // 禁止使用setState
'react/no-unknown-property': 2, // 禁止使用未知的DOM属性
'react/no-unused-prop-types': 2, // 禁止定义未使用的propTypes
'react/prefer-stateless-function': 2, // 强制 stateless Components 写成 pure function
'react/prop-types': 0, // 禁止缺少propType定义(使用ts就不需要)
'react/require-default-props': 2, // 非required prop必须有defaultProps
'react/require-render-return': 2, // render方法必须有返回值
'react/self-closing-comp': [2, {'html': false}], // 防止没有子组件的组件使用额外的结束标签
'react/sort-prop-types': 0, // propTypes按字典序排序
'react/style-prop-object': 2, // style属性必须是object
'react/sort-comp': [ // 强制class组件内的属性、生命周期等的定义顺序
2,
{
'order': [
'static-properties',
'static-methods',
'state',
'properties',
'lifecycle',
'everything-else',
'render'
],
'groups': {
'static-properties': [
'displayName',
'propTypes',
'contextTypes',
'childContextTypes',
'mixins',
'statics'
],
'lifecycle': [
'getDefaultProps',
'getInitialState',
'constructor',
'getChildContext',
'componentWillMount',
'componentDidMount',
'componentWillReceiveProps',
'shouldComponentUpdate',
'componentWillUpdate',
'componentDidUpdate',
'componentWillUnmount'
]
}
}
]
}
// Vue部分
rules: {
"vue/component-definition-name-casing": [2, "PascalCase"], // 强制组件的name使用PascalCase
"vue/html-closing-bracket-newline": [2, {"singleline": "never", "multiline": "always"}], // 统一组件关闭标签换行风格
"vue/html-closing-bracket-spacing": [2, {"startTag": "never", "endTag": "never", "selfClosingTag": "always"}], // 统一组件关闭标签空格风格
"vue/html-end-tags": 2, // 原生html标签必须有闭标签
"vue/html-indent": [2, 2, {"attribute": 1, "baseIndent": 1, "closeBracket": 0}], // html标签缩进为2
"vue/html-quotes": [2, "double"], // html属性使用双引号
"vue/html-self-closing": [2, {
"html": {
"void": "never",
"normal": "always",
"component": "always"
},
"svg": "always",
"math": "always"
}], // 没有子组件的组件标签自关闭
"vue/max-attributes-per-line": 0, // 不限制组件每行的属性数
"vue/mustache-interpolation-spacing": [2, "never"], // 模板中渲染变量的括号中不需要空格
"vue/no-multi-spaces": [2, {"ignoreProperties": false}], // 不允许出现多个无用的空格
"vue/no-spaces-around-equal-signs-in-attribute": [2], // 组件属性中的等号旁不允许有空格
"vue/no-template-shadow": 2, // 禁止在外部范围中声明的阴影变量中声明变量
"vue/prop-name-casing": [2, "camelCase"] // 组件prop命名使用camelCase
"vue/require-default-prop": 2, // 非require的prop需要有默认值
"vue/require-prop-types": 2, // 组件props必须有类型定义
"vue/v-bind-style": [2, "shorthand"], // v-bind指令必须使用缩写
"vue/v-on-style": [2, "shorthand"], // v-on指令必须使用缩写
"vue/component-tags-order": [2, {"order": ["template", "script", "style"]}], // 文件内标签定义顺序 template > script > style
"vue/order-in-components": [2, {"order": [ // 组件内容的定义顺序
"el",
"name",
"key",
"parent",
"functional",
["delimiters", "comments"],
["components", "directives", "filters"],
"extends",
"mixins",
["provide", "inject"],
"ROUTER_GUARDS",
"layout",
"middleware",
"validate",
"scrollToTop",
"transition",
"loading",
"inheritAttrs",
"model",
["props", "propsData"],
"emits",
"setup",
"asyncData",
"data",
"fetch",
"head",
"computed",
"watch",
"watchQuery",
"LIFECYCLE_HOOKS",
"methods",
["template", "render"],
"renderError"
]}],
"vue/this-in-template": [2, "never"] // 模板中无需写this
}
📝 总结
本规范涵盖了前端开发的各个方面,包括:
- ✅ 公共规范:文件命名、代码格式、编码规范
- ✅ HTML 规范:语义化标签、嵌套规范
- ✅ CSS 规范:命名、属性顺序、性能优化
- ✅ JS 规范:命名、函数、变量、异常处理
- ✅ 框架规范:Vue 和 React 的详细使用规范
- ✅ 图片规范:图片处理和优化要求
遵循本规范可以确保代码的一致性、可维护性和高质量。