==前言:为了统一编码规范,在编码完成保存后,自动校验并格式化代码,采用 Eslinat + Prettier + VScode(setting.json) 。==
1. VsCode中安装插件
首先我们需要在VsCode中安装插件:
- Eslint :限制约束代码的规范 【eslint.nodejs.cn/docs/latest...
- Prettier - Code formatter:自动格式化,美好代码。【www.prettier.cn/】
- Vetur:适用于vue2语法,用来让vscode识别.vue文件,实现语法高亮
2. 项目安装依赖
确保package.json已经有下面的内容,没有自己安装,比如:npm install @babel/eslint-parser --save-dev
perl
复制内容// package.json
{
...
"devDependencies": {
...
"@babel/core": "^7.24.3",
"@babel/eslint-parser": "^7.12.16",
"@babel/preset-env": "^7.24.3",
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/eslint-config-airbnb": "^5.0.2", // 看你需求
"@vue/eslint-config-prettier": "^7.1.0",
"@vue/eslint-config-typescript": "^5.0.2",
"babel-eslint": "^10.1.0",
"eslint": "^7.32.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^8.0.3",
}
}
==运行:npm i 安装==
3. 配置 .eslintrc.js 文件
arduino
复制内容module.exports = {
// 此项是用来告诉eslint找当前配置文件不能往父级查找
root: true,
// 此项指定环境的全局变量
env: {
browser: true, // 浏览器环境
node: true, // node环境
},
// 此项是用来提供插件的,插件名称省略了eslint-plugin-,下面这个配置是用来规范html的
// plugins: ["vue"],
// 指定javaScript语言类型和风格
parserOptions: {
ecmaVersion: 2020,
// parser: "babel-eslint"
},
// 指定eslint继承的模板
extends: [
'plugin:vue/essential',
'@vue/airbnb',
'@vue/typescript/recommended',
'plugin:vue/recommended',
'eslint:recommended',
'@vue/prettier', // 结合 .prettierrc.js
],
/** 规则 https://www.wenjiangs.com/docs/eslint,vue规则:https://eslint.vuejs.org/rules/
* 主要有如下的设置规则,可以设置字符串也可以设置数字,两者效果一致
* 'off' 或 0 - 关闭规则
* 'warn' 或 1 - 开启警告规则,使用警告级别的错误:warn (不会导致程序退出),
* 'error' 或 2 - 开启错误规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
*/
rules: {
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, // 禁止使用debugger
'no-console': 0, // 禁止使用console
'no-unused-vars': 0, // 存在声明但未使用的变量
'no-useless-escape': 0, // 禁止不必要的转义字符
'no-alert': 0, // 禁止使用 alert、confirm 和 prompt
'space-before-function-paren': [0, 'always'], // 函数定义时括号前面要不要有空格
'generator-star-spacing': 0, // 生成器函数*的前后空格
'@typescript-eslint/explicit-module-boundary-types': 0, // 函数的返回值类型必须被显式声明
'@typescript-eslint/no-empty-function': 0, // 禁止出现空函数
'@typescript-eslint/ban-types': 1, // 禁止使用特定的类型
'@typescript-eslint/no-var-requires': 0, // 禁止使用 require 语句
'arrow-parens': 0, // 箭头函数用小括号括起来
'@typescript-eslint/ban-ts-comment': 0, // 禁止使用ts的注释
'@typescript-eslint/no-unused-vars': 0, // 禁止出现未使用过的变量
'@typescript-eslint/no-this-alias': 0, // 禁止将 this 别名
'@typescript-eslint/no-inferrable-types': 0, // 禁止使用隐式 any 类型
'@typescript-eslint/no-extra-semi': 0, // 禁止不必要的分号
'prefer-const': 0, // 推荐使用const
'@typescript-eslint/no-explicit-any': 0, // 禁止使用any类型
'@typescript-eslint/no-empty-interface': 0, // 禁止空接口
'@typescript-eslint/no-non-null-assertion': 0, // 禁止使用!后缀运算符
'vue/no-side-effects-in-computed-properties': 1, // 禁止在计算属性中对属性修改
'linebreak-style': 'off', // 换行风格
'class-methods-use-this': 'off', // 确保在类的方法中没有无效的this引用
'import/no-cycle': [0, { ignoreExternal: true }], // 防止在 JavaScript 项目中导入路径产生循环引用
'global-require': 'off', // 检查是否在 ESLint 文件中全局调用了 require 函数
'no-unused-expressions': 'off', // 检查在 JavaScript 代码中是否有无用的表达式
'no-plusplus': 'off', // 禁止使用自增(++)和自减(--)操作符
'no-underscore-dangle': 'off', // 禁止使用前导下划线命名变量或函数
'no-tabs': 'off', // 禁止代码中的 tab 字符的使用,因为 tab 容易造成代码缩进混乱
'max-len': 'off', // 限制一行代码的最大长度
'no-async-promise-executor': 'warn', // 禁止在 Promise 构造函数中使用 async 函数作为执行器
'no-param-reassign': 'warn', // 禁止对函数参数进行重新赋值
'quotes': ['error', 'single'], // 指定字符串是否必须使用单引号'或双引号"
'no-nested-ternary': 'off', // 禁止使用嵌套的三元运算符
'complexity': ['off', 30], // 限制函数的复杂度
'vue/attributes-order': 'off', // 禁止在组件中使用未排序的属性
'lines-between-class-members': 'off', // 禁止类成员之间出现空行
'camelcase': [2, { properties: 'never' }], // 强制使用骆驼拼写法或强制使用小写单词拼写法
},
}
4. .eslintignore ESLint 忽略特定的文件和目录
根据实际情况自己配置
bash
复制内容# ESLint 忽略特定的文件和目录
node_modules/
/dist
/public
/src/libs
/docs/*.html
*.html
**/services
src/mock/data
src/mock/auto
*.min.js
**/auto
/*.json
src/api/*
5. 配置 .prettierrc.js 文件
java
复制内容module.exports = {
semi: false, // 尽可能不要分号
singleQuote: true, // 尽可能使用单引号
trailingComma: 'all', // 尽可能使用尾随逗号
endOfLine: 'lf', // endOfLine: "<lf|crlf|cr|auto>" 行尾换行符,默认是lf,
htmlWhitespaceSensitivity: 'ignore', // 根据显示样式决定 html 要不要折行
bracketSameLine: true, // 控制对象文字中的大括号是否应该与行内的代码保持在同一行
printWidth: 200, // 一行代码的最大字符数,默认是80(printWidth: <int>)
// tabWidth: 4, // tab宽度为4空格(tabWidth: <int>)
useTabs: false, // 是否使用tab来缩进,我们使用空格(useTabs: <bool>)
quoteProps: 'consistent', // object对象中key值是否加引号(quoteProps: "<as-needed|consistent|preserve>")as-needed只有在需求要的情况下加引号,consistent是有一个需要引号就统一加,preserve是保留用户输入的引号
bracketSpacing: true, // object对象里面的key和value值和括号间的空格(bracketSpacing: <bool>)
arrowParens: 'always', // 箭头函数单个参数的情况是否省略括号,默认always是总是带括号(arrowParens: "<always|avoid>")
vueIndentScriptAndStyle: false, // vue script和style标签中是否缩进,开启可能会破坏编辑器的代码折叠
singleAttributePerLine: true,
}
注:prettierrc的优先级高于eslint。 如果修改了.prettierrc的配置选项,会发现 eslint 和 prettier又冲突了,这是因为vscode插件缓存没有及时更新,重启下vscode即可。
6. .prettierignore 忽略不想格式化的文件
根据实际情况自己配置
bash
复制内容# 忽略不想格式化的文件
/dist
/public
/src/libs
/docs/*.html
*.html
**/services
src/mock/data
src/mock/auto
*.min.js
**/auto
7. 项目中根目录下 .vscode 的配置
复制内容┌─根目录
│ ├─.vscode
│ │ └─settings.json
settings.json
json
复制内容{
"files.eol": "\n", // 文件结束符
"eslint.format.enable": true, // 开启保存时自动修复
"editor.codeLens": true, // 显示行号
"editor.tabSize": 4, // 重新设定tabsize
"editor.detectIndentation": false, // 禁用自动检测缩进
// 将prettier设置为默认格式化程序(在编辑器中有可能被其他Formatter占用,所以将prettier设置为默认Formatter)
"editor.defaultFormatter": "esbenp.prettier-vscode",
// 关闭js/ts的默认format,统一用eslint进行格式化(tslint已经不维护了,所以转eslint吧)
"javascript.format.enable": false,
"typescript.format.enable": false,
// 保存时自动格式化 (根据根目录下'.prettierrc文件配置项')
"editor.formatOnSave": true,
// Enable per-language
"[html]": {
"editor.defaultFormatter": "vscode.html-language-features",
"editor.formatOnSave": true
},
"[vue]": {
"editor.formatOnSave": true, // 交给 eslint
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
},
"vetur.format.defaultFormatterOptions": {
"prettier": {
// Prettier option here
"trailingComma": "es5", // 多行时,尽可能打印尾随的逗号
"tabWidth": 4, // 会忽略vetur的tabSize配置
"useTabs": false, // 是否利用tab替代空格
"semi": false, // 句尾是否加;
"singleQuote": true, // 使用单引号而不是双引号
"arrowParens": "avoid" // allow paren-less arrow functions 箭头函数的参数使用圆括号
}
},
// 什么类型的文件需要遵守stylelint规则
"stylelint.validate": [
"css",
"less",
"postcss",
"scss",
"sass",
"vue"
],
// 为ESLint启用"保存时自动修复",并且仍然具有格式和快速修复功能
"editor.codeActionsOnSave": {
"source.fixAll": true,
},
// 关闭vetur的js/ts/html的formatter。html用eslint-plugin-vue格式化。
// js/ts程序用eslint,防止vetur中的prettier与eslint格式化冲突
"vetur.format.defaultFormatter.ts": "none",
"vetur.validation.script": true,
"vetur.format.options.tabSize": 4,
"vetur.format.options.useTabs": false,
"vetur.format.defaultFormatter.html": "js-beautify-html",
"vetur.format.defaultFormatter.js": "prettier",
"[markdown]": {
"editor.defaultFormatter": null,
"editor.formatOnSave": false
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "stylelint.vscode-stylelint"
}
}
8. .editorconfig
帮助开发人员在不同的编辑器和IDE之间定义和维护一致的编码样式规范的工具。
ini
复制内容# 控制.editorconfig文件是否生效
root = true
# 匹配全部文件
[*]
# 设置字符集
charset = utf-8
# 缩进风格,可选"space、tab"
indent_style = space
# 缩进空格数
indent_size = 4
# 结尾换行符,可选"lf、cr、crlf"
end_of_line = lf
# 在文件结尾插入新行
insert_final_newline = true
# 删除一行中的前后空格
trim_trailing_whitespace = true
9. 在package.json配置eslint修复项目的命令
json
复制内容{
...
"scripts": {
...
"eslint": "eslint --ext .js,.ts,.vue src --fix"
},
}
效果:保存前:
保存后:
10. stylelint 格式化css
10.1 安装依赖
css
复制内容{
"scripts": {
...
"stylelint:fix": "stylelint src/**/*.{html,vue,css,less,scss,sass} --fix"
},
"dependencies": {
...
"stylelint": "~13.6.1",
"stylelint-config-prettier": "~8.0.2",
"stylelint-order": "~4.1.0",
"postcss": "~8.4.16",
"postcss-html": "0.36.0",
"postcss-pxtorem": "~5.1.1"
}
}
10.1 .stylelintignore
ruby
复制内容dist/*
node_modules/*
packages/*
public/*
zzglpc/*
10.2 .stylelintrc.js
ruby
复制内容module.exports = {
extends: ['stylelint-config-prettier'],
plugins: ['stylelint-order'],
rules: {
'order/order': ['custom-properties', 'declarations'],
// 参考:https://github.com/csscomb/csscomb.js/blob/master/config/zen.json
'order/properties-order': [
'position',
'top',
'right',
'bottom',
'left',
'z-index',
'display',
'visibility',
'float',
'clear',
'overflow',
'-ms-overflow-x',
'-ms-overflow-y',
'overflow-x',
'overflow-y',
'-webkit-overflow-scrolling',
'clip',
'-webkit-align-content',
'-ms-flex-line-pack',
'align-content',
'-webkit-box-align',
'-moz-box-align',
'-webkit-align-items',
'align-items',
'-ms-flex-align',
'-webkit-align-self',
'-ms-flex-item-align',
'-ms-grid-row-align',
'align-self',
'-webkit-box-flex',
'-webkit-flex',
'-moz-box-flex',
'-ms-flex',
'flex',
'-webkit-flex-flow',
'-ms-flex-flow',
'flex-flow',
'-webkit-flex-basis',
'-ms-flex-preferred-size',
'flex-basis',
'-webkit-box-orient',
'-webkit-box-direction',
'-webkit-flex-direction',
'-moz-box-orient',
'-moz-box-direction',
'-ms-flex-direction',
'flex-direction',
'-webkit-flex-grow',
'-ms-flex-positive',
'flex-grow',
'-webkit-flex-shrink',
'-ms-flex-negative',
'flex-shrink',
'-webkit-flex-wrap',
'-ms-flex-wrap',
'flex-wrap',
'-webkit-box-pack',
'-moz-box-pack',
'-ms-flex-pack',
'-webkit-justify-content',
'justify-content',
'-webkit-box-ordinal-group',
'-webkit-order',
'-moz-box-ordinal-group',
'-ms-flex-order',
'order',
'-webkit-box-sizing',
'-moz-box-sizing',
'box-sizing',
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'padding',
'padding-top',
'padding-right',
'padding-bottom',
'padding-left',
'min-width',
'min-height',
'max-width',
'max-height',
'width',
'height',
'outline',
'outline-width',
'outline-style',
'outline-color',
'outline-offset',
'border',
'border-spacing',
'border-collapse',
'border-width',
'border-style',
'border-color',
'border-top',
'border-top-width',
'border-top-style',
'border-top-color',
'border-right',
'border-right-width',
'border-right-style',
'border-right-color',
'border-bottom',
'border-bottom-width',
'border-bottom-style',
'border-bottom-color',
'border-left',
'border-left-width',
'border-left-style',
'border-left-color',
'-webkit-border-radius',
'-moz-border-radius',
'border-radius',
'-webkit-border-top-left-radius',
'-moz-border-radius-topleft',
'border-top-left-radius',
'-webkit-border-top-right-radius',
'-moz-border-radius-topright',
'border-top-right-radius',
'-webkit-border-bottom-right-radius',
'-moz-border-radius-bottomright',
'border-bottom-right-radius',
'-webkit-border-bottom-left-radius',
'-moz-border-radius-bottomleft',
'border-bottom-left-radius',
'-webkit-border-image',
'-moz-border-image',
'-o-border-image',
'border-image',
'-webkit-border-image-source',
'-moz-border-image-source',
'-o-border-image-source',
'border-image-source',
'-webkit-border-image-slice',
'-moz-border-image-slice',
'-o-border-image-slice',
'border-image-slice',
'-webkit-border-image-width',
'-moz-border-image-width',
'-o-border-image-width',
'border-image-width',
'-webkit-border-image-outset',
'-moz-border-image-outset',
'-o-border-image-outset',
'border-image-outset',
'-webkit-border-image-repeat',
'-moz-border-image-repeat',
'-o-border-image-repeat',
'border-image-repeat',
'-webkit-border-top-image',
'-moz-border-top-image',
'-o-border-top-image',
'border-top-image',
'-webkit-border-right-image',
'-moz-border-right-image',
'-o-border-right-image',
'border-right-image',
'-webkit-border-bottom-image',
'-moz-border-bottom-image',
'-o-border-bottom-image',
'border-bottom-image',
'-webkit-border-left-image',
'-moz-border-left-image',
'-o-border-left-image',
'border-left-image',
'-webkit-border-corner-image',
'-moz-border-corner-image',
'-o-border-corner-image',
'border-corner-image',
'-webkit-border-top-left-image',
'-moz-border-top-left-image',
'-o-border-top-left-image',
'border-top-left-image',
'-webkit-border-top-right-image',
'-moz-border-top-right-image',
'-o-border-top-right-image',
'border-top-right-image',
'-webkit-border-bottom-right-image',
'-moz-border-bottom-right-image',
'-o-border-bottom-right-image',
'border-bottom-right-image',
'-webkit-border-bottom-left-image',
'-moz-border-bottom-left-image',
'-o-border-bottom-left-image',
'border-bottom-left-image',
'background',
'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader',
'background-color',
'background-image',
'background-attachment',
'background-position',
'-ms-background-position-x',
'-ms-background-position-y',
'background-position-x',
'background-position-y',
'-webkit-background-clip',
'-moz-background-clip',
'background-clip',
'background-origin',
'-webkit-background-size',
'-moz-background-size',
'-o-background-size',
'background-size',
'background-repeat',
'box-decoration-break',
'-webkit-box-shadow',
'-moz-box-shadow',
'box-shadow',
'color',
'table-layout',
'caption-side',
'empty-cells',
'list-style',
'list-style-position',
'list-style-type',
'list-style-image',
'quotes',
'content',
'counter-increment',
'counter-reset',
'-ms-writing-mode',
'vertical-align',
'text-align',
'-webkit-text-align-last',
'-moz-text-align-last',
'-ms-text-align-last',
'text-align-last',
'text-decoration',
'text-emphasis',
'text-emphasis-position',
'text-emphasis-style',
'text-emphasis-color',
'text-indent',
'-ms-text-justify',
'text-justify',
'text-outline',
'text-transform',
'text-wrap',
'-ms-text-overflow',
'text-overflow',
'text-overflow-ellipsis',
'text-overflow-mode',
'text-shadow',
'white-space',
'word-spacing',
'-ms-word-wrap',
'word-wrap',
'-ms-word-break',
'word-break',
'-moz-tab-size',
'-o-tab-size',
'tab-size',
'-webkit-hyphens',
'-moz-hyphens',
'hyphens',
'letter-spacing',
'font',
'font-weight',
'font-style',
'font-variant',
'font-size-adjust',
'font-stretch',
'font-size',
'font-family',
'src',
'line-height',
'opacity',
"-ms-filter:progid:DXImageTransform.Microsoft.Alpha",
'filter:progid:DXImageTransform.Microsoft.Alpha(Opacity',
'-ms-interpolation-mode',
'-webkit-filter',
'-ms-filter',
'filter',
'resize',
'cursor',
'nav-index',
'nav-up',
'nav-right',
'nav-down',
'nav-left',
'-webkit-transition',
'-moz-transition',
'-ms-transition',
'-o-transition',
'transition',
'-webkit-transition-delay',
'-moz-transition-delay',
'-ms-transition-delay',
'-o-transition-delay',
'transition-delay',
'-webkit-transition-timing-function',
'-moz-transition-timing-function',
'-ms-transition-timing-function',
'-o-transition-timing-function',
'transition-timing-function',
'-webkit-transition-duration',
'-moz-transition-duration',
'-ms-transition-duration',
'-o-transition-duration',
'transition-duration',
'-webkit-transition-property',
'-moz-transition-property',
'-ms-transition-property',
'-o-transition-property',
'transition-property',
'-webkit-transform',
'-moz-transform',
'-ms-transform',
'-o-transform',
'transform',
'-webkit-transform-origin',
'-moz-transform-origin',
'-ms-transform-origin',
'-o-transform-origin',
'transform-origin',
'-webkit-animation',
'-moz-animation',
'-ms-animation',
'-o-animation',
'animation',
'-webkit-animation-name',
'-moz-animation-name',
'-ms-animation-name',
'-o-animation-name',
'animation-name',
'-webkit-animation-duration',
'-moz-animation-duration',
'-ms-animation-duration',
'-o-animation-duration',
'animation-duration',
'-webkit-animation-play-state',
'-moz-animation-play-state',
'-ms-animation-play-state',
'-o-animation-play-state',
'animation-play-state',
'-webkit-animation-timing-function',
'-moz-animation-timing-function',
'-ms-animation-timing-function',
'-o-animation-timing-function',
'animation-timing-function',
'-webkit-animation-delay',
'-moz-animation-delay',
'-ms-animation-delay',
'-o-animation-delay',
'animation-delay',
'-webkit-animation-iteration-count',
'-moz-animation-iteration-count',
'-ms-animation-iteration-count',
'-o-animation-iteration-count',
'animation-iteration-count',
'-webkit-animation-direction',
'-moz-animation-direction',
'-ms-animation-direction',
'-o-animation-direction',
'animation-direction',
'pointer-events',
'unicode-bidi',
'direction',
'-webkit-columns',
'-moz-columns',
'columns',
'-webkit-column-span',
'-moz-column-span',
'column-span',
'-webkit-column-width',
'-moz-column-width',
'column-width',
'-webkit-column-count',
'-moz-column-count',
'column-count',
'-webkit-column-fill',
'-moz-column-fill',
'column-fill',
'-webkit-column-gap',
'-moz-column-gap',
'column-gap',
'-webkit-column-rule',
'-moz-column-rule',
'column-rule',
'-webkit-column-rule-width',
'-moz-column-rule-width',
'column-rule-width',
'-webkit-column-rule-style',
'-moz-column-rule-style',
'column-rule-style',
'-webkit-column-rule-color',
'-moz-column-rule-color',
'column-rule-color',
'break-before',
'break-inside',
'break-after',
'page-break-before',
'page-break-inside',
'page-break-after',
'orphans',
'widows',
'-ms-zoom',
'zoom',
'max-zoom',
'min-zoom',
'user-zoom',
'orientation',
],
},
}