前端开发代码规范

4/8/2022 代码规范

在团队协作开发中,每个开发者编码习惯不同、代码风格迥异,为了代码高可用、可维护性,我们利用工具指定以下规范:

# 1.Vue代码风格指南

首先,请阅读Vue代码风格指南 (opens new window),对Vue的文件、组件以及api中的一些命名规范有个基本的了解。

# 2.Javascript风格指南

这是谷歌的Javascript风格指南《Google JavaScript Style Guide (opens new window)

PS:可以用翻译软件进行翻译阅读

# 3.CSS命名规范之BEM

GET BEM(http://getbem.com/introduction/) (opens new window)

BEM的意思就是块(block)、元素(element)、修饰符(modifier),是由Yandex团队提出的一种前端命名方法论。这种巧妙的命名方法让你的CSS类对其他开发者来说更加透明而且更有意义。
命名约定的模式如下:

.block{}
.block__element{}
.block--modifier{}
1
2
3
  • .block 代表了更高级别的抽象或组件。
  • .block__element 代表.block的后代,用于形成一个完整的.block的整体。
  • .block--modifier代表.block的不同状态或不同版本。

例1. el-tabs的子元素 eltabs

<div class="el-tabs el-tabs--card el-tabs--top">
    <div class="el-tabs__header is-top">...</div>
    <div class="el-tabs__content">...</div>
</div>
1
2
3
4

其中的“__header”、“__content”就是el-tabs不同组成部分的子元素。

例2. el-button的修饰符

elbutton

<button type="button" class="el-button el-button--default">
    <span>默认按钮</span>
</button>
<button type="button" class="el-button el-button--primary">
    <span>主要按钮</span>
</button>
<button type="button" class="el-button el-button--success">
    <span>成功按钮</span>
</button>
<button type="button" class="el-button el-button--info">
    <span>信息按钮</span>
</button>
<button type="button" class="el-button el-button--warning">
    <span>警告按钮</span>
</button>
<button type="button" class="el-button el-button--danger">
    <span>危险按钮</span>
</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

其中的“--default”、“--primary”、“--success”、“--info”、“--warning”、“--danger”就属于修饰符(modifier),用来表示同一个元素的不同状态。

# 4.EditorConfig

EditorConfig是一个支持不同IDE、编辑器环境的编辑器配置插件。

# 4.1 在VS Code扩展中下载安装此应用。

Editor

# 4.2 在项目根目录添加.editorconfig文件

# http://editorconfig.org
root = true
 
# 说明
## 设置文件编码为 UTF-8;
## 用两个空格代替制表符;
## 在保存时删除尾部的空白字符;
## 在文件结尾添加一个空白行;
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
quote_type = single
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
 
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

# 5.ESLint

ESLint 是一个在 JavaScript 代码中通过规则模式匹配作代码识别和报告的插件化的检测工具,它的目的是保证代码规范的一致性和及时发现代码问题、提前避免错误发生。 ESLint 的关注点是代码质量,检查代码风格并且会提示不符合风格规范的代码。除此之外 ESLint 也具有一部分代码格式化的功能。

# 5.1 全局下载Eslint

npm install -g eslint
1

# 5.2 ESLint扩展程序(VSCode)

eslint

# 5.3 ESLint配置文件

在项目根目录创建.eslintrc.js文件

// https://eslint.org/docs/user-guide/configuring

module.exports = {
  root: true,
  parserOptions: {
    parser: 'babel-eslint',
    sourceType: 'module',
  },
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  extends: ['plugin:vue/recommended', 'eslint:recommended'],

  // add your custom rules here
  // it is base on https://github.com/vuejs/eslint-config-vue
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'vue/first-attribute-linebreak': [
      1,
      {
        multiline: 'beside',
      },
    ],
    'vue/max-attributes-per-line': [
      2,
      {
        singleline: {
          max: 1
        },
        multiline: {
          max: 1
        }
      }
    ],
    'vue/html-self-closing': [
      'error',
      {
        html: {
          void: 'any',
          normal: 'any',
          component: 'any',
        },
        svg: 'any',
        math: 'any',
      },
    ],
    'vue/singleline-html-element-content-newline': 'off',
    'vue/no-parsing-error': [
      2,
      { 'invalid-first-character-of-tag-name': false },
    ],
    'vue/no-use-v-if-with-v-for': 'off',
    'vue/multiline-html-element-content-newline': 'off',
    'vue/name-property-casing': [0, 'PascalCase'],
    'vue/html-closing-bracket-newline': [
      0,
      {
        singleline: 'never',
        multiline: 'always',
      },
    ],
    'vue/no-side-effects-in-computed-properties': 0,
    'accessor-pairs': 2, //在对象中使用getter/setter
    'arrow-spacing': [
      2,
      {
        before: true,
        after: true,
      },
    ], //=>的前/后括号
    'block-spacing': [2, 'always'], //块是否需要空格
    // if while function 后面的{必须与if在同一行,java风格。
    'brace-style': [
      2,
      '1tbs',
      {
        allowSingleLine: true,
      },
    ],
    //强制驼峰法命名
    camelcase: [
      0,
      {
        properties: 'always',
      },
    ],
    // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号,
    // always-multiline:多行模式必须带逗号,单行模式不能带逗号
    'comma-dangle': [2, 'never'],
    // 控制逗号前后的空格
    'comma-spacing': [
      2,
      {
        before: false,
        after: true,
      },
    ],
    'comma-style': [2, 'last'], // 控制逗号在行尾出现还是在行首出现
    // 强制在子类构造函数中用super()调用父类构造函数,TypeScrip的编译器也会提示
    'constructor-super': 2,
    // 强制object.key 中 . 的位置,参数:
    // property,'.'号应与属性在同一行
    // object, '.' 号应与对象名在同一行
    'dot-location': [2, 'property'],
    'eol-last': 2, // 文件末尾强制换行
    eqeqeq: [2, 'allow-null'], // 使用 === 替代 ==
    'generator-star-spacing': 0, //生成器函数*的前后空格
    'handle-callback-err': 0, //nodejs 处理错误
    indent: [
      2,
      2,
      {
        //缩进风格
        SwitchCase: 1,
      },
    ],
    // JSX 属性中一致使用双引号或单引号
    'jsx-quotes': [2, 'prefer-single'],
    //对象字面量中冒号的前后空格
    'key-spacing': [
      2,
      {
        beforeColon: false,
        afterColon: true,
      },
    ],
    'keyword-spacing': [
      2,
      {
        before: true,
        after: true,
      },
    ],
    //函数名首行大写必须使用new方式调用,首行小写必须用不带new方式调用
    'new-cap': [
      2,
      {
        newIsCap: true,
        capIsNew: false,
      },
    ],
    'new-parens': 2, //new时必须加小括号
    'no-array-constructor': 2, //禁止使用数组构造器
    'no-caller': 2, //禁止使用arguments.caller或arguments.callee
    'no-console': process.env.NODE_ENV === 'production' ? 2 : 0, //禁止使用console
    'no-class-assign': 2, //禁止给类赋值
    'no-cond-assign': 2, //禁止在条件表达式中使用赋值语句
    'no-const-assign': 2, //禁止修改const声明的变量
    'no-control-regex': 0, //禁止在正则表达式中使用控制字符
    'no-delete-var': 2, //不能对var声明的变量使用delete操作符
    'no-dupe-args': 2, //函数参数不能重复
    'no-dupe-class-members': 2, //不允许类中出现重复的声明
    'no-dupe-keys': 2, //在创建对象字面量时不允许键重复 {a:1,a:1}
    'no-duplicate-case': 2, //switch中的case标签不能重复
    'no-empty-character-class': 0, //正则表达式中的[]内容不能为空
    'no-empty-pattern': 0,
    'no-eval': 0, //禁止使用eval
    'no-ex-assign': 2, //禁止给catch语句中的异常参数赋值
    'no-extend-native': 2, //禁止扩展native对象
    'no-extra-bind': 2, //禁止不必要的函数绑定
    'no-extra-boolean-cast': 2, //禁止不必要的bool转换
    'no-extra-parens': [2, 'functions'], //禁止非必要的括号
    'no-fallthrough': 2, //禁止switch穿透
    'no-floating-decimal': 2, //禁止省略浮点数中的0 .5 3.
    'no-func-assign': 2, //禁止重复的函数声明
    'no-implied-eval': 2, //禁止使用隐式eval
    'no-inner-declarations': [2, 'functions'], //禁止在块语句中使用声明(变量或函数)
    'no-invalid-regexp': 2, //禁止无效的正则表达式
    'no-irregular-whitespace': 2, //不能有不规则的空格
    'no-iterator': 2, //禁止使用__iterator__ 属性
    'no-label-var': 2, //label名不能与var声明的变量名相同
    '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': [
      0,
      {
        max: 1,
      },
    ], //空行最多不能超过1行
    'no-native-reassign': 2, //不能重写native对象
    'no-negated-in-lhs': 2, //in 操作符的左边不能有!
    'no-new-object': 2, //禁止使用new Object()
    'no-new-require': 2, //禁止使用new require
    'no-new-symbol': 2, //禁止使用new symbol
    'no-new-wrappers': 2, //禁止使用new创建包装实例,new String new Boolean new Number
    'no-obj-calls': 0, //不能调用内置的全局对象,比如Math() JSON()
    'no-octal': 2, //禁止使用八进制数字
    'no-octal-escape': 2, //禁止使用八进制转义序列
    'no-path-concat': 2, //node中不能使用__dirname或__filename做路径拼接
    'no-proto': 2, //禁止使用__proto__属性
    'no-redeclare': 2, //禁止重复声明变量
    'no-regex-spaces': 2, //禁止在正则表达式字面量中使用多个空格 /foo bar/
    'no-return-assign': [2, 'except-parens'], //return 语句中不能有赋值表达式
    'no-self-assign': 2, //自我分配
    'no-self-compare': 2, //不能比较自身
    'no-sequences': 2, //禁止使用逗号运算符
    'no-shadow-restricted-names': 2, //严格模式中规定的限制标识符不能作为声明时的变量名使用
    'no-spaced-func': 2, //函数调用时 函数名与()之间不能有空格
    'no-sparse-arrays': 2, //禁止稀疏数组, [1,,2]
    'no-this-before-super': 2, //在调用super()之前不能使用this或super
    'no-throw-literal': 2, //禁止抛出字面量错误 throw "error";
    'no-trailing-spaces': 0, //一行结束后面不要有空格
    'no-undef': 2, //不能有未定义的变量
    'no-undef-init': 2, //变量初始化时不能直接给它赋值为undefined
    'no-unexpected-multiline': 0, //避免多行表达式
    'no-unmodified-loop-condition': 0, //检查引用是否在循环中被修改
    'no-unneeded-ternary': 0, //禁止不必要的嵌套 var isYes = answer === 1 ? true : false;
    'no-unreachable': 2, //不能有无法执行的代码
    'no-unsafe-finally': 0,
    'no-unused-vars': [
      2,
      {
        vars: 'all',
        args: 'none',
      },
    ], //不能有声明后未被使用的变量或参数
    'no-useless-call': 2, //禁止不必要的call和apply
    'no-useless-computed-key': 0, //没有必要使用带文字的计算属性
    'no-useless-constructor': 2, //可以在不改变类的工作方式的情况下安全地移除的类构造函数
    'no-useless-escape': 0,
    'no-whitespace-before-property': 0,
    'no-with': 2, //禁用with
    'one-var': 0, //连续声明
    'operator-linebreak': [
      2,
      'after',
      {
        overrides: {
          '?': 'before',
          ':': 'before',
        },
      },
    ], //换行时运算符在行尾还是行首
    'padded-blocks': 0, //块语句内行首行尾是否要空行
    quotes: [
      2,
      'single',
      {
        avoidEscape: true,
        allowTemplateLiterals: true,
      },
    ], //引号类型 `` "" ''
    semi: [2, 'always'], //语句强制分号结尾
    'semi-spacing': [
      2,
      {
        before: false,
        after: true,
      },
    ], //分号前后空格
    'space-before-blocks': [2, 'always'], //不以新行开始的块{前面要不要有空格
    'space-before-function-paren': [2, 'never'], //函数定义时括号前面要不要有空格
    'space-in-parens': [2, 'never'], //小括号里面要不要有空格
    'space-infix-ops': 2, //中缀操作符周围要不要有空格
    'space-unary-ops': [
      2,
      {
        words: true,
        nonwords: false,
      },
    ], //一元运算符的前/后要不要加空格
    'spaced-comment': 0, //注释风格不要有空格什么的
    'template-curly-spacing': [2, 'never'],
    'use-isnan': 2, //禁止比较时使用NaN,只能用isNaN()
    'valid-typeof': 2, //必须使用合法的typeof的值
    'wrap-iife': [2, 'any'], //立即执行函数表达式的小括号风格
    'yield-star-spacing': 0,
    yoda: [2, 'never'], //禁止尤达条件
    'prefer-const': 2, //首选const
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, //禁止使用debugger
    'object-curly-spacing': [
      2,
      'always',
      {
        objectsInObjects: false,
      },
    ], //大括号内是否允许不必要的空格
    'array-bracket-spacing': [2, 'never'], //是否允许非空数组里面有多余的空格
    'vue/component-name-in-template-casing': [
      'error',
      'kebab-case',
      {
        registeredComponentsOnly: false,
        ignores: [],
      },
    ], // vue组件在template中的命令使用kebab-case
    'vue/prop-name-casing': ['error', 'camelCase'],
    'vue/require-prop-types': 'error',
    'vue/require-v-for-key': 'error',
  },
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306

# 6.Prettier

Prettier是一个诞生于2016年就迅速流行起来的专注于代码格式化的工具。
Prettier只关注格式化,并不具有lint检查语法等能力。它通过解析代码并匹配自己的一套规则,来强制执行一致的代码展示格式。 它在美化代码方面有很大的优势,配合ESLint可以对ESLint格式化基础上做一个很好的补充。

# Prettier扩展程序

prettier

# 7.Vetur(VS Code扩展程序)

Vetur是VS Code的Vue辅助工具,具有语法高亮、快捷代码段、格式化等功能。
在格式化方面,可以配合prettier使用。 vetur

# 8.VS Code 配置文件

在项目根目录创建.vscode文件夹,文件夹下面创建settings.json配置文件

{
  // 点击保存时,根据 eslint 规则自定修复,同时集成 prettier 到 eslint 中
  "editor.formatOnSave": true, // Require a 'prettierconfig' to format prettier
  // 使能每一种语言默认格式化规则
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[scss]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[jsonc]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[vue]": {
    "editor.defaultFormatter": "octref.vetur"
  },
  "vetur.validation.template": false,
  "vetur.format.defaultFormatter.html": "js-beautify-html",
  "vetur.format.defaultFormatter.js": "prettier-eslint",
  "vetur.format.defaultFormatter.scss": "prettier",
  "vetur.format.defaultFormatterOptions": {
    "prettier": {
      "singleQuote": true, // 使用单引号
      "trailingComma": "none",
      "semi": true // 末尾使用分号
    },
    "js-beautify-html": {
      "wrap_attributes": "force-aligned"
    }
  },
  // Enable/disable default JavaScript formatter (For Prettier)
  "javascript.format.enable": false,
  /*  prettier的配置 */
  "prettier.printWidth": 100, // 超过最大值换行
  "prettier.tabWidth": 2, // 缩进字节数
  "prettier.useTabs": false, // 缩进不使用tab,使用空格
  "prettier.semi": true, // 句尾添加分号
  "prettier.singleQuote": true, // 使用单引号代替双引号
  "prettier.proseWrap": "preserve", // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
  "prettier.arrowParens": "avoid", //  (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
  "prettier.bracketSpacing": true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
  "prettier.disableLanguages": ["vue"], // 不格式化vue文件,vue文件的格式化单独设置
  "prettier.endOfLine": "auto", // 结尾是 \n \r \n\r auto
  "prettier.htmlWhitespaceSensitivity": "ignore",
  "prettier.ignorePath": ".prettierignore", // 不使用prettier格式化的文件填写在项目的.prettierignore文件中
  "prettier.jsxBracketSameLine": false, // 在jsx中把'>' 是否单独放一行
  "prettier.jsxSingleQuote": false, // 在jsx中使用单引号代替双引号
  "prettier.requireConfig": false,
  "prettier.trailingComma": "none", // 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60