首发于 银匠屋
详解VSCode 格式化不符合预期的问题

详解VSCode 格式化不符合预期的问题

一句话总结

不同格式化程序执行时长不一样,导致文件格式好后和预期不符。

请务必保持校验(Lint提示)规则和格式化(Format)规则一致,不然格式化后还是不符合预期是非常讨厌的。

我们保证单一职责,一种文件只使用一个格式化程序,其余的formatter全部禁用。

本篇主要讲解怎么调教VSCode的保存时格式化程序。

常见问题

项目既有prettier又有eslint,二者相互打架,导致格式化代码后,格式反复横跳。

适用人员

本文用于解决各类格式化冲突问题,如何使用 vscode自带格式化/ESLint/TSLint/Prettier 不在本文讨论范围之内。

看完本文你将收获:

  1. 为什么格式化后依然报错?
  2. 为什么有时候会格式化两次?

现状

多数VSCode使用者安装了冲突的格式化插件,但却不知道如何设置。

一个编辑器里对某个类型的文件有多个Formatter(格式化执行者),是一定会打架的。

常见格式程序执行 时长( 自测

prettier > default > eslint

意味着 通常情况下 prettier 最后执行完毕。代码样式就由prettier决定了。如果你既用了ESLint又用了Prettier,在ESLint格式化好后,再prettier格式化不就闪烁了吗?

格式化的类型及设置

Shift + Option + F : 手动执行格式化程序,这个命令调用的是该文件格式的默认格式化程序。

//这样写就是将js用eslint格式化 
 "[javascript]": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
// 这样是用vscode的默认ts格式化工具
"[javascriptreact]": {
        "editor.defaultFormatter": "vscode.typescript-language-features"
    },


不同平台执行快捷键不一,见:

若有多个格式化程序,可能会让你选用哪个进行格式化。

Save时格式化

下面的json型设置需要写到setting.json里,详情请看:

// 保存时使用VSCode 自身格式化程序格式化
"editor.formatOnSave": true,
// 保存时用eslint格式化
"editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
// 两者会在格式化js时冲突,所以需要关闭默认js格式化程序 
"javascript.format.enable": false

上面讲了eslint和自带格式化程序的自动保存格式化的设置方法,prettier请自行学习吧。

配置的优先级为当前目录下的.vscode/settings.json优先级高于user中的设置json。

有哪些格式化程序和插件?

一、VSCode自带格式化程序

以js为例

// 代表默认格式js程序是否开启,默认开启。用eslint格式化js时需要设置为false
// 既然用ESLint进行格式校验,一定也用ESLint来格式化是最能匹配的
"javascript.format.enable": true 

只有一些普适型的格式化规则,够正常适用。

无任何其他格式化插件时执行此格式化程序。

二、ESlint

按照eslint的规则进行格式化,格式化之后eslint还报错不是eslint的原因,是后面又有其他格式化程序格式化成了其他格式。

eslint.validate 无须设置,基本没有意义。

eslint-plugin-vue 可以管到vue文件的html部分。

设置eslint为格式化程序后,发现不好用?点击底部ESlint按钮,看看有没有什么报错?

三、vetur

VSCode 商店里的 Vue 插件 。用于在 Vue 单文件中展示不同语言,有格式化、展示、高亮等能力。

安装即默认开启格式化。

// 关闭vetur内的js格式化程序 
"vetur.format.defaultFormatter.js": "none",

vetur 内置了 prettier 和 eslint 的能力。实测prettier的执行慢于eslint。所以会出现Vue文件中js格式化后eslint还报错的情况。

prettier: For css/scss/less/js/ts.
prettier-eslint: For js. Run prettier and eslint --fix.
prettyhtml: For html.
stylus-supremacy: For stylus.
vscode-typescript: For js/ts. The same js/ts formatter for VS Code.

四、prettier

格式化界的钢铁直男,他有一套自己的格式化规则。

安装即默认开启保存格式化,手动格式化也会触发prettier。 例如若安装了 prettier,vscode 里的所有右下角有 prettier 的均有 prettier 托管格式化,默认程序似乎就不起作用了。

即使不安装 vetur,prettier 也会格式化 vue 文件

总结

格式化由 VSCode 执行,但可能执行者可能是很多种,这是导致格式化‘ 不好用 ’的根源所在。

VSCode 本身有个格式化程序

eslint 可以执行格式化 js

prettier 可以执行格式化 js html css 等

vetur 可以执行格式化 vue 单文件中的各类语言

例如: pretter里的indent 缩进默认为 2,可通过"prettier.tabWidth": 4 修改

VSCode如何判断应该使用哪种格式化工具?

文件后缀识别。
不同的文件在 VSCode 里被识别成不同的语言格式,展示在编辑器下方的状态栏里,这非常关键。

所以vue文件通常会被vetur格式化而不是其他的。

prettier 和 eslint 同时格式化

prettier 和 eslint 的 "source.fixAll.eslint": true 若同时存在,会格式化两次(能肉眼可见),最后会以 prettier 的为准。

prettier-eslint

未尝试过,不敢妄断。

按照官方文档是用eslint的规则进行格式化。 使用prettier的格式化能力,使用eslint的格式化规则(eslint的格式化有时候不好用)。

推荐设置

本人设置,仅供参考

以下配置切勿照搬,需要理解原理。如果你有eslint的格式化项目也有tslint的格式化项目,需要对每个项目进行特殊配置。

插件安装

dbaeumer.vscode-eslint(用于eslint报错和格式化)

octref.vetur(用于vue文件识别)

sibiraj-s.vscode-scss-formatter(vscode没有自动格式化css的程序,用于格式化css和less等)

以下文件可以先放在项目下尝试(团队协作传到git),比较实用时定在user下的setting里即可

 {
  // 以下程序用于格式化Vue项目,其他项目可以根据原理一通百通。
  // 设置保存时格式化。只用于用于格式化css/less程序
  "editor.formatOnSave": true,
  // 关闭js/ts的默认format,统一用eslint进行格式化(tslint已经不维护了,所以转eslint吧)
  "javascript.format.enable": false,
  "typescript.format.enable": false,
  // 关闭vetur的js/ts/html的formatter。html用eslint-plugin-vue格式化。
  // js/ts程序用eslint,防止vetur中的prettier与eslint格式化冲突
  "vetur.format.defaultFormatter.html": "none",
  "vetur.format.defaultFormatter.js": "none",
  "vetur.format.defaultFormatter.ts": "none",
  // 开启eslint自动修复js/ts/jsx/tsx功能
  "eslint.format.enable": true,
  // 设置js的formatter为eslint
  "[javascript]": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  "[typescript]": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  "[scss]": {
    "editor.defaultFormatter": "sibiraj-s.vscode-scss-formatter"
  "[json]": {
    "editor.defaultFormatter": "vscode.json-language-features"
  // jsonc是有注释的json
  "[jsonc]": {
    "editor.defaultFormatter": "vscode.json-language-features"
  "eslint.codeActionsOnSave.mode": "problems",
  "eslint.validate": [
    "typescript",
    "javascript",
    "javascriptreact",
    "typescriptreact",
  // 将json文件识别为jsonc格式