手把手教你VsCode正确解决vue3+Eslint+prettier+Vetur的配置冲突
- VsCode正确解决vue3+Eslint+prettier+Vetur的配置冲突
- Eslint文档查看和修改规则:
- step1:首先快速浏览下规则简要
- setp2: ctrl+F 搜索你要配置规则的英文名,例如attribute
- setp3: 修改配置文件
- Prettier修改项目配置文件和Vscode设置
- step1: 查看官方文档:
- setp2: 修改配置文件
- Vetur的Vscode配置
- setp1:Vetur官方文档
- 最后给VsCode的配置,供参考:
VsCode正确解决vue3+Eslint+prettier+Vetur的配置冲突
最近在做vue项目,需要配置代码规范,看了网上很多的配置案例,发现千篇一律,都有问题,不是Eslint冲突就是Vetur冲突,最后查阅官方文档解决这次问题,注:本案例通用Vscode配置setting.json
首先给出官方文档,可以照着官方文档编写项目的配置以及vscode的setting.json
Eslint: https://eslint.vuejs.org/rules/
根据需要配置.eslintrc.cjs
Prettier: https://prettier.io/docs/en/options
根据需要配置.eslintrc.cjs
Vetur: https://vuejs.github.io/vetur/guide/formatting.html#formatters
Vetur需要在VsCode的setting.json中配置
本次案例主要解决Eslint和Vetur自动保存后多属性换行冲突问题,其他问题也可参考这个配置
Eslint文档查看和修改规则:
以官方文档为主,因为Eslint检测到Vetur自动保存后属性换行报错,修改Prettier无济于事,于是想到查看官方文档,搜索如下:
step1:首先快速浏览下规则简要
setp2: ctrl+F 搜索你要配置规则的英文名,例如attribute
最后找到这两个规则:
‘vue/first-attribute-linebreak’:
‘vue/html-closing-bracket-newline’:
利用Edge翻译后意思很明确,官方文档也给出了示例,如下图所示:
setp3: 修改配置文件
'vue/first-attribute-linebreak': ['error',{singleline: 'ignore',multiline: 'ignore',},],'vue/html-closing-bracket-newline': ['error',{singleline: 'never',multiline: 'always',selfClosingTag: {singleline: 'never',multiline: 'always',},},],
将这两个规则插入到.eslintrc.cjs可以屏蔽属性换行和标签换行的检测
Prettier修改项目配置文件和Vscode设置
step1: 查看官方文档:
主要看options这一栏,明确规则的详情后,我们就知道如何配置Vscode和项目中的.prettierrc.json 文件
setp2: 修改配置文件
这里建议先修改vscode的setting.json,将官方Options中建议的设置添加上去。快捷键Ctrl+shift+P
我选的是打开用户设置,针对当前用户有效
这里给出我自己的设置项: (部分修改prettier的默认项)
//====== prettier格式化,能使每一种语言默认格式化规则 ======"editor.defaultFormatter": "esbenp.prettier-vscode","eslint.alwaysShowStatus": true, // 总是显示eslint状态"prettier.printWidth": 120, // 超过最大值换行"prettier.tabWidth": 2, // 缩进字节数"prettier.useTabs": false, // 缩进不使用tab,使用空格"prettier.semi": false, // 句尾添加分号"prettier.singleQuote": true, // 使用单引号代替双引号"prettier.proseWrap": "preserve", // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行"prettier.arrowParens": "always", // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号"prettier.bracketSpacing": true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }""prettier.endOfLine": "lf", // 结尾是 \n \r \n\r auto// "prettier.eslintIntegration": false, //不让prettier使用eslint的代码格式进行校验"prettier.htmlWhitespaceSensitivity": "ignore","prettier.ignorePath": ".prettierignore", // 不使用prettier格式化的文件填写在项目的.prettierignore文件中"prettier.bracketSameLine": false, // 在jsx中把'>' 是否单独放一行 true--不会单独占一行,false--折行"prettier.jsxSingleQuote": false, // 在jsx中使用单引号代替双引号// "prettier.parser": "babylon", // 格式化的解析器,默认是babylon"prettier.requireConfig": false, // Require a 'prettierconfig' to format prettier// "prettier.stylelintIntegration": false, //不让prettier使用stylelint的代码格式进行校验"prettier.trailingComma": "all", // 属性值es5表示在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)"prettier.vueIndentScriptAndStyle": false,"prettier.singleAttributePerLine": false,// "prettier.tslintIntegration": false,"notebook.codeActionsOnSave": {}, // 不让prettier使用tslint的代码格式进行校验
以上配置可以在.prettierrc.json中添加,但是没必要,只需要给出你想覆盖的几项就可以,一般脚手架会自动填充几项,我自己手动添加printWidth和sigleAttributePerLine
.prettierrc.json
{"printWidth": 120,"singleQuote": true,"semi": false,"bracketSpacing": true,"htmlWhitespaceSensitivity": "ignore","endOfLine": "auto","trailingComma": "all","tabWidth": 2,"singleAttributePerLine": false
}
如果你配置了Vscode的自动保存设置,项目会优先读取工程的prettier设置,然后才是vscode的设置来对代码格式化
Vetur的Vscode配置
改步骤比较关键,是解决Vetur和prettier格式化代码冲突的关键,也是影响到Eslint语法检查的关键
setp1:Vetur官方文档
强烈建议阅读Formatting栏
先在setting.json中添加vetur的默认配置:
{"vetur.format.defaultFormatter.html": "prettier","vetur.format.defaultFormatter.pug": "prettier","vetur.format.defaultFormatter.css": "prettier","vetur.format.defaultFormatter.postcss": "prettier","vetur.format.defaultFormatter.scss": "prettier","vetur.format.defaultFormatter.less": "prettier","vetur.format.defaultFormatter.stylus": "stylus-supremacy","vetur.format.defaultFormatter.js": "prettier","vetur.format.defaultFormatter.ts": "prettier","vetur.format.defaultFormatter.sass": "sass-formatter"
}
然后修改vetur的默认格式化操作:
例如:
"vetur.format.defaultFormatterOptions": {
“js-beautify-html”: {},
"prettyhtml": {},"prettier": {// Prettier option here"semi": false}}
注意:
1.prettyhtml已经弃用了,可以不用配置
2.prettier配置表示vetur格式化会按照prettier规则进行格式化,前提是本地没有提供.prettiercs.json文件,具体查看官方文档说明
3.js-beautify-html很关键, 这是和prettier以及eslint格式化冲突的关键,原因是在一项默认配置中,
“vetur.format.defaultFormatter.html”: “prettier”, 这个参数可以写成js-beautify-html。
改了之后会 按照js-beautify-html的规则进行格式化,这是造成规则冲突的关键。如何解决: 一本万利,直接用prettier。如果坚持使用js-beautify-html,要确保js-beautify-html的配置项不被Eslint警告,这是关键。
怎么查看js-beautify-html的默认配置项,官方文档解释了,阅读git-hub的源代码:
将这个默认配置值复制到vscode中,如下:
"vetur.format.defaultFormatterOptions": {"js-beautify-html": {"end_with_newline": false, // End output with newline"indent_char": " ", // Indentation character"indent_handlebars": false, // e.g. {{#foo}}, {{/foo}}"indent_inner_html": false, // Indent <head> and <body> sections"indent_scripts": "keep", // [keep|separate|normal]"indent_size": 2, // Indentation size"indent_with_tabs": false,"max_preserve_newlines": 1, // Maximum number of line breaks to be preserved in one chunk (0 disables)"preserve_newlines": true, // Whether existing line breaks before elements should be preserved"unformatted": [], // Tags that shouldn't be formatted. Causes mis-alignment"wrap_line_length": 120, // Lines should wrap at next opportunity after this number of characters (0 disables)"wrap_attributes": "auto"// Wrap attributes to new lines [auto|force|force-aligned|force-expand-multiline] ["auto"]},}
其中我们只需要关注wrap_line_lengt和wrap_attributes这两个属性,wrap_attributes确保你的标签属性是佛换行,auto表示不换行,wrap_line_length表示一行的最大长度,超过之后搭配auto可自动换行,其他换行可自行实验。
最后给VsCode的配置,供参考:
{//====== 通用选项 ======// "terminal.integrated.shell.windows": "C:\\WINDOWS\\System32\\cmd.exe","npm.packageManager": "npm","workbench.statusBar.visible": true,"window.zoomLevel": 0,"window.newWindowDimensions": "inherit","window.openFoldersInNewWindow": "on",// "workbench.iconTheme": "vscode-icons",//"workbench.colorTheme": "Solarized Dark" //暗阴//"workbench.colorTheme": "Monokai Dimmed" //暗暖//"workbench.colorTheme": "Monokai" //暗凉//"workbench.colorTheme": "Visual Studio Light" //亮//====== vscode自带格式化功能配置 ======"editor.mouseWheelZoom": true,"editor.cursorWidth": 3,"editor.renderLineHighlight": "all",// "editor.renderWhitespace": "selection",//文本自动换行"editor.fontSize": 16,"editor.wordWrap": "on","editor.renderWhitespace": "all","search.followSymlinks": false,"editor.formatOnSave": true,"editor.formatOnType": true,"editor.formatOnPaste": true,"editor.detectIndentation": false, //关闭检测第一个tab后面就tab"editor.renderControlCharacters": true, //制表符显示->"editor.insertSpaces": true, //转为空格"editor.tabSize": 2, //tab为四个空格"typescript.updateImportsOnFileMove.enabled": "always","javascript.format.semicolons": "ignore", //格式化时不删除也不添加 ,默认有三种: ignore, insert, remove"typescript.format.semicolons": "ignore","javascript.format.insertSpaceBeforeFunctionParenthesis": false, //函数名与()间加空隔"javascript.preferences.quoteStyle": "single","typescript.preferences.quoteStyle": "single","javascript.format.enable": true, //自带默认javascript格式化"typescript.format.enable": true, //自带默认typescript格式化"json.format.enable": true, //自带默认json格式化"html.format.indentInnerHtml": false, //自带默认html格式化//====== prettier格式化,能使每一种语言默认格式化规则 ======"editor.defaultFormatter": "esbenp.prettier-vscode","eslint.alwaysShowStatus": true, // 总是显示eslint状态"prettier.printWidth": 120, // 超过最大值换行"prettier.tabWidth": 2, // 缩进字节数"prettier.useTabs": false, // 缩进不使用tab,使用空格"prettier.semi": false, // 句尾添加分号"prettier.singleQuote": true, // 使用单引号代替双引号"prettier.proseWrap": "preserve", // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行"prettier.arrowParens": "always", // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号"prettier.bracketSpacing": true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }""prettier.endOfLine": "lf", // 结尾是 \n \r \n\r auto// "prettier.eslintIntegration": false, //不让prettier使用eslint的代码格式进行校验"prettier.htmlWhitespaceSensitivity": "ignore","prettier.ignorePath": ".prettierignore", // 不使用prettier格式化的文件填写在项目的.prettierignore文件中"prettier.bracketSameLine": false, // 在jsx中把'>' 是否单独放一行 true--不会单独占一行,false--折行"prettier.jsxSingleQuote": false, // 在jsx中使用单引号代替双引号// "prettier.parser": "babylon", // 格式化的解析器,默认是babylon"prettier.requireConfig": false, // Require a 'prettierconfig' to format prettier// "prettier.stylelintIntegration": false, //不让prettier使用stylelint的代码格式进行校验"prettier.trailingComma": "all", // 属性值es5表示在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)"prettier.vueIndentScriptAndStyle": false,"prettier.singleAttributePerLine": false,// "prettier.tslintIntegration": false,"notebook.codeActionsOnSave": {}, // 不让prettier使用tslint的代码格式进行校验// // --- 部分文件格式化在后面单独设置 ---// "prettier.disableLanguages": [// "vue",// "typescript",// "javascript",// "jsonc"// ],//====== 单独设置文件格式化 ======"[jsonc]": {"editor.defaultFormatter": "vscode.json-language-features"},"[javascript]": {// "editor.defaultFormatter": "vscode.typescript-language-features""editor.defaultFormatter": "esbenp.prettier-vscode"},"[typescript]": {// "editor.defaultFormatter": "vscode.typescript-language-features""editor.defaultFormatter": "esbenp.prettier-vscode"},"[html]": {// "editor.defaultFormatter": "vscode.html-language-features"// "editor.defaultFormatter": "rvest.vs-code-prettier-eslint""editor.defaultFormatter": "vscode.html-language-features"},"[less]": {"editor.defaultFormatter": "esbenp.prettier-vscode"},"[scss]": {// "editor.defaultFormatter": "vscode.css-language-features""editor.defaultFormatter": "esbenp.prettier-vscode"},// ------ 用vetur格式化vue文件配置 ------"[vue]": {"editor.defaultFormatter": "octref.vetur"},"vetur.format.defaultFormatter.html": "js-beautify-html", //默认是prettier"vetur.format.defaultFormatter.css": "prettier","vetur.format.defaultFormatter.postcss": "prettier","vetur.format.defaultFormatter.scss": "prettier","vetur.format.defaultFormatter.less": "prettier","vetur.format.defaultFormatter.stylus": "stylus-supremacy",//"vetur.format.defaultFormatter.js": "prettier", //解决不了 函数名与()间需要加空隔的需求//"vetur.format.defaultFormatter.ts": "prettier", //同上"vetur.format.defaultFormatter.js": "vscode-typescript", //解决不了 双引号需要自动转单引号的需求, 不过通过eslint插件保存时自动修复"vetur.format.defaultFormatter.ts": "vscode-typescript", //同上//vetur的自定义设置"vetur.format.defaultFormatterOptions": {"js-beautify-html": {"end_with_newline": false, // End output with newline"indent_char": " ", // Indentation character"indent_handlebars": false, // e.g. {{#foo}}, {{/foo}}"indent_inner_html": false, // Indent <head> and <body> sections"indent_scripts": "keep", // [keep|separate|normal]"indent_size": 2, // Indentation size"indent_with_tabs": false,"max_preserve_newlines": 1, // Maximum number of line breaks to be preserved in one chunk (0 disables)"preserve_newlines": true, // Whether existing line breaks before elements should be preserved"unformatted": [], // Tags that shouldn't be formatted. Causes mis-alignment"wrap_line_length": 120, // Lines should wrap at next opportunity after this number of characters (0 disables)"wrap_attributes": "auto"// Wrap attributes to new lines [auto|force|force-aligned|force-expand-multiline] ["auto"]},// "prettyhtml": { 已经被弃用了// // "printWidth": 100, //使用不同的最大行长度// "singleQuote": true,// // "wrapAttributes": false, //强制换行属性(当它有多个时,默认值为false)// "sortAttributes": false //按字母顺序排序属性(默认值:false)// },"prettier": {"printWidth": 120,"semi": false, //代码行后面需不需要生成分号"singleQuote": true, //需不需要把双引号格式化成单引号"trailingComma": "all" //在任何可能的多行中输入尾逗号。}},// "html.format.wrapAttributes": "auto",// ====== eslint 保存时自动修复格式配置 ======"editor.codeActionsOnSave": {"source.fixAll.eslint": "explicit"},"eslint.validate": ["javascript","javascriptreact","typescript","typescriptreact","html","vue","less"// "scss",],"eslint.format.enable": true,"eslint.run": "onType","git.ignoreMissingGitWarning": true,"explorer.confirmDelete": false,"files.autoSave": "onFocusChange","vetur.validation.template": false,"vetur.validation.script": false,"vetur.validation.style": false,"files.associations": {"*.vue": "vue"},"cssrem.rootFontSize": 80,"open-in-browser.default": "Chrome",
}
.prettierc.json
{"printWidth": 120,"singleQuote": true,"semi": false,"bracketSpacing": true,"htmlWhitespaceSensitivity": "ignore","endOfLine": "auto","trailingComma": "all","tabWidth": 2,"singleAttributePerLine": false
}
.eslintrc.cjs
{......rules: {// eslint(https://eslint.bootcss.com/docs/rules/)'no-var': 'error', // 要求使用 let 或 const 而不是 var'no-multiple-empty-lines': ['warn', { max: 1 }], // 不允许多个空行'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off','no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off','no-unexpected-multiline': 'error', // 禁止空余的多行'no-useless-escape': 'off', // 禁止不必要的转义字符// typeScript (https://typescript-eslint.io/rules)'@typescript-eslint/no-unused-vars': 'error', // 禁止定义未使用的变量'@typescript-eslint/prefer-ts-expect-error': 'error', // 禁止使用 @ts-ignore'@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型'@typescript-eslint/no-non-null-assertion': 'off','@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。'@typescript-eslint/semi': 'off',// eslint-plugin-vue (https://eslint.vuejs.org/rules/)'vue/multi-word-component-names': 'off', // 要求组件名称始终为 “-” 链接的单词'vue/script-setup-uses-vars': 'error', // 防止<script setup>使用的变量<template>被标记为未使用'vue/no-mutating-props': 'off', // 不允许组件 prop的改变'vue/attribute-hyphenation': 'off', // 对模板中的自定义组件强制执行属性命名样式'vue/first-attribute-linebreak': ['error',{singleline: 'ignore',multiline: 'ignore',},],'vue/html-closing-bracket-newline': ['error',{singleline: 'never',multiline: 'always',selfClosingTag: {singleline: 'never',multiline: 'always',},},],},
}