当我还是个菜鸟的时候,我只知道eslint就是个校验代码规范性的一个插件,但是我在使用中老是绝对很麻烦。加了这个东西,我的代码到处飘红。但是运行也没问题。很恼火。然后我又有强迫症,就一个一个去改,特别麻烦。
现在我也算是个小组长,当和组员协同的时候,发现有些同事的代码规范性确实不高,按照自己想写的来,不影响运行的报红就放那儿不管,换行缩进也不统一。我想是时候需要总结一下在提升代码规范和质量的同时,也不影响开发进度的方法了。
准备工作
为了完整的体验整个配置流程,会从一个空文件夹开始。
-
首先初始化一个项目
npm init
。 -
新建一个index.js 文件,随便写点儿不规范的代码。
javascriptconst a = "a" console.log(b)
现在是不会有任何提示与报错。我们期望的是,对于变量a ,应该给出提示未被使用 ,对于打印的变量b ,应该提示未被定义 ,对于字符串定义,想要是单引号 ,最后每句结尾加上分号。
eslint
作用: 它可以规范你的代码 写法和检查代码 中不易察觉的小bug。
安装: pnpm i -D eslint
。
初始化eslint: npm init @eslint/config
或者npx eslint --init
。如果执行命令半天没反应就把终端关了再开。
选择相应的配置之后就会生成 .eslintrc.js。这个就是eslint的配置文件,当前还有很多其它类型文件,根据自己喜好来就行。
然后去安装vscode插件
安装完成后,就可以看到之前写的代码已经报错了。
这就是eslint帮助检测代码的功能。 然后字符串是单引号还是双引号,结尾加不加分号就需要另外加配置了。
eslint配置
每个规则都可以设置的三个值
- "off" 或 0 - 关闭规则
- "warn" 或 1 - 启用并视作警告(不影响退出)
- "error" 或 2 - 启用并视作错误(触发时退出代码为 1)
现在配置文件中的 rules 还是空的,需要自己加配置。
JSON
rules: {
semi: 2, // 句尾使用分号
quotes: [2, 'single'], // 使用单引号代替双引号
}
加上配置之后,index.js文件就出现了相应的报错,提示需要加上分号和使用单引号。
修复
知道哪儿不符合规范和有问题就需要改过来。我们不会做那种一个个改出来的蠢事儿(虽然我以前做过)。
指令
首先介绍一个指令的方式修复 npx eslint index.js --fix
。执行完之后双引号转为单引号,结尾分号也加上了。但是对于变量的报错是无法修复的。它也不可能直接给你删掉。具体哪些规则可以修复可以查阅官方文档
下面规则后面带这个logo的就是可以被修复的。
自动修复
有个问题: 谁没事儿写完一段代码就去执行一个修复命令,这也太闲了。期望的是能够边写边修复是最好的。
打开vscode设置: 文件 => 首选项 => 设置
或者 ctrl + ,
然后点击右上角的这个logo,转为json文件编辑。
添加下面的配置:
JSON
"editor.formatOnType": true,
"editor.formatOnSave": true,
"eslint.codeAction.showDocumentation": {
"enable": true
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": ["javascript", "javascriptreact", "html", "vue"],
如果有重复就以这里为准。 现在,当你保存的时候eslint就会自动修复那些可以被修复的问题。
补充: 自动创建的eslint配置文件没有把vue加入到环境中。所以在配置文件中加入
JSON
env: {
browser: true,
es2021: true,
node: true,
vue: true, // vue文件的支持
},
prettier
作用: prettier是一个代码美化工具,具体作用于制表符的缩进等功能。
安装: pnpm i -D prettier
配置
根目录创建一个文件 .prettierrc.json。
JSON
{
"tabWidth": 3
}
这个配置会将缩进设置为3个空格(仅作演示,正常来说是2个)。
修复
指令
npx prettier --write index.js
vscode
肯定还得是vscode配置啦。 还是同一个vscode配置文件,添加以下配置。可以根据自己需要添加其它类型文件的支持。
JSON
"[html]": {
"editor.defaultFormatter": "vscode.html-language-features"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
安装vscode插件
执行保存后就发现制表符是三个空格了。
vscode工作区配置
多人开发项目的时候,每个人本地得vscode配置肯定不同。上面的配置都是在你的vscode中配置的。所有项目都会生效,但是当别人拿过去用,别人就不一定能生效。因为你的配置他没有。所以需要一个所有人参与这个项目的人都能使用的配置。
项目根目录下创建 .vscode 文件夹。文件夹内可以创建以下配置文件。
settings.json
作用: 此文件配置可以覆盖掉vscode内的配置。
JSON
{
"editor.fontSize": 30 // 字体大小为30
}
这个配置只会在当前工作区生效,新开一个vscode窗口是不会生效的。
extensions.json
作用: 当前项目推荐安装的vscode插件。
比如你上面的vscode设置都得是安装了 prettier和eslint 插件的。当别人开发这个项目没有安装的时候,就可以给予提示安装。
无需自己创建配置文件。
xxxxxxx.code-snippets:项目中共享的代码片段
快捷式生成代码片段。
eslint配置规则参考
JSON
module.exports = {
root: true, // 当前配置为根配置,将不再从上级文件夹查找配置
parserOptions: {
parser: 'babel-eslint', // 采用 babel-eslint 作为语法解析器
sourceType: 'module' // 指定来源的类型,有两种script或module
},
env: {
browser: true, // 设置为所需检查的代码是在浏览器环境运行的
node: true, // 设置为所需检查的代码是nodejs环境运行的
es6: true // 设置所需检查代码为es6语法书写
},
// 配置js全局变量,因为是uni-app,全局的uni是不需要引入的
globals: {
uni: 'readonly',
wx: 'readonly',
},
extends: ['plugin:vue/recommended', 'eslint:recommended', 'plugin:prettier/recommended'], // 扩展使用 vue 检查规则和eslint推荐规则
rules: {
'prettier/prettier': 'error',
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', // 只有开发环境可以使用console
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', // 只有开发环境可以使用debugger
'vue/attribute-hyphenation': 0, // 忽略属性连字
'vue/max-attributes-per-line':[2, { singleline: 10, multiline: { max: 1, allowFirstLine: false } }], // 每行最大属性
'vue/singleline-html-element-content-newline': 'off', // 单行html元素内容在新的一行
'vue/multiline-html-element-content-newline': 'off', // 多行html元素内容在新的一行
'vue/html-closing-bracket-newline': 'off', // html右括号在新的一行
'vue/no-v-html': 'off', // 不使用v-html
'vue/html-self-closing': 0, // 忽略html标签自闭合
'accessor-pairs': 2, // 应同时设置setter和getter
'arrow-spacing': [2, { before: true, after: true }], // 箭头间距
'vue/require-default-prop': 0, // 不检查默认属性
'vue/require-prop-types': 0, // 不检查默认类型
'block-spacing': [2, 'always'], // 块间距
'brace-style': [2, '1tbs', { allowSingleLine: true }], // 大括号样式允许单行
'camelcase': [2, { properties: 'always' }], // 为属性强制执行驼峰命名
'comma-dangle': [2, 'never'], // 逗号不使用悬挂
'comma-spacing': [2, { before: false, after: true }], // 逗号间距
'comma-style': [2, 'last'], //(默认)与数组元素,对象属性或变量声明在同一行之后和同一行需要逗号
'constructor-super': 2,
'consistent-this': [2, 'that'], // 强制this别名为that
'curly': [2, 'multi-line'], // 当一个块只包含一条语句时,不允许省略花括号。
'dot-location': [2, 'property'], //成员表达式中的点应与属性部分位于同一行
'eol-last': 2, // 强制文件以换行符结束(LF)
'eqeqeq': ['error', 'always', { null: 'ignore' }], // 强制使用全等
'generator-star-spacing': [2, { before: true, after: true }], // 生成器中'*'两侧都要有间距
'global-require': 1, // 所有调用require()都位于模块的顶层
'indent': [2, 2, { SwitchCase: 2 }], // 缩进风格
'key-spacing': [2, { beforeColon: false, afterColon: true }], // 强制在对象字面量属性中的键和值之间保持一致的间距
'keyword-spacing': [2, { before: true, after: true }], // 关键字如if/function等的间距
'new-cap': [2, { newIsCap: true, capIsNew: false }],// 允许在没有new操作符的情况下调用大写启动的函数;(默认)要求new使用大写启动函数调用所有操作符
'new-parens': 2, // JavaScript通过new关键字调用函数时允许省略括号
'no-array-constructor': 1, // 不允许使用Array构造函数。除非要指定生成数组的长度
'no-class-assign': 2, // 不允许修改类声明的变量
'no-const-assign': 2, // 不能修改使用const关键字声明的变量
'no-control-regex': 0, // 不允许正则表达式中的控制字符
'no-delete-var': 2, // 不允许在变量上使用delete操作符
'no-dupe-args': 2, // 不允许在函数声明或表达式中使用重复的参数名称
'no-dupe-class-members': 2, // 不允许在类成员中使用重复的参数名称
'no-dupe-keys': 2, // 不允许在对象文字中使用重复键
'no-duplicate-case': 2, // 不允许在switch语句的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-boolean-cast': 2, // 禁止不必要的布尔转换
'no-extra-parens': [2, 'functions'], // 仅在函数表达式附近禁止不必要的括号
'no-fallthrough': 2, //消除一个案件无意中掉到另一个案件
'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, // 消除阴影变量声明
'no-label-var': 2, // 禁止创建与范围内的变量共享名称的标签
'no-labels': [2, { allowLoop: false, allowSwitch: false }], // 消除 JavaScript 中使用带标签的语句
'no-lone-blocks': 2, // 消除脚本顶层或其他块中不必要的和可能混淆的块
'no-mixed-spaces-and-tabs': 2, // 不允许使用混合空格和制表符进行缩进
'no-multi-spaces': 2, // 禁止在逻辑表达式,条件表达式,声明,数组元素,对象属性,序列和函数参数周围使用多个空格
'no-multi-str': 2, // 防止使用多行字符串
'no-multiple-empty-lines': [2, { max: 1 }], // 最多一个空行
'no-native-reassign': 2, // 不允许修改只读全局变量
'no-new-object': 2, // 不允许使用Object构造函数
'no-new-require': 2, // 消除new require表达的使用
'no-new-symbol': 2, // 防止Symbol与new 同时使用的意外错误
'no-new-wrappers': 2, // 杜绝使用String,Number以及Boolean与new操作
'no-obj-calls': 2, // 不允许调用Math,JSON和Reflect对象作为功能
'no-octal': 2, // 不允许使用八进制文字
'no-octal-escape': 2, // 不允许字符串文字中的八进制转义序列
'no-path-concat': 2, // 防止 Node.js 中的目录路径字符串连接无效
'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-sparse-arrays': 2, // 不允许稀疏数组文字
'no-this-before-super': 2, // 在呼call前标记this/super关键字super()
'no-throw-literal': 2, // 不允许抛出不可能是Error对象的文字和其他表达式
'no-trailing-spaces': 2, // 不允许在行尾添加尾随空白
'no-undef': 2, // 任何对未声明的变量的引用都会导致错误
'no-undef-init': 2, // 消除初始化为undefined的变量声明
'no-underscore-dangle': 2, // 标识符不能以_开头或结尾
'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, // 不允许return,throw,break,和continue里面的语句finally块
'no-unused-vars': [2, { vars: 'all', args: 'after-used' }],
// 消除未使用的变量,函数和函数的参数
// vars: 'all' 检查所有变量的使用情况,包括全局范围内的变量。这是默认设置。 args: 'after-used' 只有最后一个参数必须使用。例如,这允许您为函数使用两个命名参数,并且只要您使用第二个参数,ESLint 就不会警告您第一个参数。这是默认设置。
'no-useless-call': 2, // 标记使用情况,Function.prototype.call()并且Function.prototype.apply()可以用正常的函数调用来替代
'no-useless-computed-key': 2, // 禁止不必要地使用计算属性键
'no-useless-constructor': 2, // 在不改变类的工作方式的情况下安全地移除的类构造函数
'no-useless-escape': 0, // 禁用不必要的转义字符
'no-whitespace-before-property': 2, // 如果对象的属性位于同一行上,不允许围绕点或在开头括号之前留出空白
'no-with': 2, // 禁用with
'no-var': 2, // 禁用var
'one-var': [2, { initialized: 'never' }], // 强制将变量声明为每个函数(对于var)或块(对于let和const)范围一起声明或单独声明。 initialized: 'never' 每个作用域要求多个变量声明用于初始化变量
'operator-linebreak': [2, 'after', { overrides: { '?': 'before', ':': 'before' } }], // 实施一致的换行
'padded-blocks': [2, 'never'], // 在块内强制执行一致的空行填充
'prefer-destructuring': ['error', { object: false, array: false }], // 此规则强制使用解构而不是通过成员表达式访问属性。
'quotes': [2, 'single', { avoidEscape: true, allowTemplateLiterals: true }], // avoidEscape: true 允许字符串使用单引号或双引号,只要字符串包含必须以其他方式转义的引号 ;allowTemplateLiterals: true 允许字符串使用反引号
'radix': 2, // parseInt必须指定第二个参数
'semi': [2, 'never'], // 不使用分号
'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 }], // words: true 如:new,delete,typeof,void,yield 左右必须有空格 // nonwords: false 一元运算符,如:-,+,--,++,!,!!左右不能有空格
'spaced-comment': [2, 'always', { markers: ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] }], // 注释开始后,此规则将强制间距的一致性//或/*
'template-curly-spacing': [2, 'never'], // 不允许大括号内的空格
'use-isnan': 2, // 禁止比较时使用NaN,只能用isNaN()
'valid-typeof': 2, // 必须使用合法的typeof的值
'wrap-iife': [2, 'any'], // 立即执行函数表达式的小括号风格
'yield-star-spacing': [2, 'both'], // 强制执行*周围 yield*表达式的间距,两侧都必须有空格
'yoda': [2, 'never'],
'prefer-const': 2, // 使用let关键字声明的变量,但在初始分配后从未重新分配变量,应改为const声明
'object-curly-spacing': [2, 'always', { objectsInObjects: false }], // 不允许以对象元素开始和/或以对象元素结尾的对象的大括号内的间距
'array-bracket-spacing': [2, 'never'] // 不允许数组括号内的空格
}
}
prettier配置参考
JSON
{
"printWidth": 175, // 每行代码长度(默认175)
"trailingComma": "none", // 在对象或数组最后一个元素后面是否加逗号
"tabWidth": 2, // 每个tab相当于多少个空格(默认2)
"useTabs": true, // 使用tab(制表符)缩进而非空格
"semi": false, // 是否在行尾加分号
"singleQuote": true, // 使用单引号代替双引号
"arrowParens": "avoid", // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
"bracketSpacing": true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
"proseWrap": "preserve", // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
"htmlWhitespaceSensitivity": "ignore", // HTML 文件空格敏感度
"jsxBracketSameLine": true // 将>多行JSX元素放在最后一行的末尾,而不是单独放在下一行
}