目录
[二、VS Code设置格式化规范](#二、VS Code设置格式化规范)
一、概述
工欲善其事,必先利其器。在团队开发过程中,代码提交格式不统一的情况时有发生,这会导致在查看代码更新时效率降低、不便追溯。本文将针对这一问题,介绍如何构建一套有效的项目代码格式化架构。
本篇文章将从以下两个方面梳理解决方案:一是在 VS Code 中实现本地代码格式化统一,二是通过 Prettier 配置确保项目中的代码格式优先统一。
二、VS Code设置格式化规范
1、插件推荐安装
Tailwind CSS IntelliSense
Tailwind Sorter
Less IntelliSense
SCSS IntelliSense
CSS Modules
ES7+ React/Redux/React-Native snippets
React PropTypes Intellisense
React Native Tools
ESLint
Prettier - Code formatter
Path Intellisense
Error Lens
GitLess
Material Icon Theme
Solarized Light (no bold) -> Solarized Light
Project Manager
Todo Tree
Expo Tools
2、Setting.json统一
这里关键在于统一格式化属性,使用Prettier插件格式化
javascript
{
"workbench.settings.applyToAllProfiles": [],
"workbench.iconTheme": "material-icon-theme",
"diffEditor.ignoreTrimWhitespace": true,
"react-native-tools.showUserTips": false,
// 字体调大更护眼
"editor.fontSize": 14,
"editor.lineHeight": 1.6,
// 降低对比度 - 柔和的米色主题
"workbench.colorCustomizations": {
"editor.background": "#f9f3e4",
// ========== 活动栏(最左侧) ==========
"activityBar.background": "#F7F2E7",
"activityBar.foreground": "#666666",
"activityBar.inactiveForeground": "#999999",
"activityBar.border": "#E8E4DD",
"activityBarBadge.background": "#D4C8B5",
"activityBarBadge.foreground": "#333333",
// ========== 侧边栏 ==========
"sideBar.background": "#F8F6F2",
"sideBar.foreground": "#444444",
"sideBar.border": "#E8E4DD",
"sideBarSectionHeader.background": "#F0EDE8",
"sideBarTitle.foreground": "#555555",
// ========== 标题栏 ==========
"titleBar.activeBackground": "#F6F4F0",
"titleBar.activeForeground": "#444444",
"titleBar.inactiveBackground": "#F9F7F3",
"titleBar.inactiveForeground": "#888888",
"titleBar.border": "#E8E4DD",
// ========== 状态栏 ==========
"statusBar.background": "#F5F1EB",
"statusBar.foreground": "#555555",
"statusBar.border": "#E8E4DD",
"statusBar.noFolderBackground": "#F5F1EB",
"statusBar.debuggingBackground": "#E8DCC8",
"statusBarItem.remoteBackground": "#D4C8B5",
// ========== 标签页 ==========
"tab.activeBackground": "#FAF9F6",
"tab.activeForeground": "#222222",
"tab.inactiveBackground": "#F0EDE8",
"tab.inactiveForeground": "#666666",
"tab.border": "#E8E4DD",
"tab.activeBorder": "#D4C8B5",
"tab.activeBorderTop": "#C4B8A5",
"tab.hoverBackground": "#F5F1EB",
"tab.unfocusedHoverBackground": "#F5F1EB",
// ========== 编辑器组和面板 ==========
"editorGroupHeader.tabsBackground": "#F0EDE8",
"editorGroup.border": "#E8E4DD",
"panel.background": "#FAF9F6",
"panel.border": "#E8E4DD",
"panelTitle.activeForeground": "#444444",
"panelTitle.inactiveForeground": "#888888",
// ========== 输入框和下拉菜单 ==========
"input.background": "#FFFFFF",
"input.foreground": "#333333",
"input.border": "#E8E4DD",
"inputOption.activeBorder": "#C4B8A5",
"dropdown.background": "#FFFFFF",
"dropdown.border": "#E8E4DD",
"dropdown.foreground": "#333333",
// ========== 按钮 ==========
"button.background": "#D4C8B5",
"button.foreground": "#333333",
"button.hoverBackground": "#C4B8A5",
"button.border": "#C4B8A5",
// ========== 滚动条 ==========
"scrollbar.shadow": "#E8E4DD",
"scrollbarSlider.background": "#D4C8B599",
"scrollbarSlider.hoverBackground": "#C4B8A599",
"scrollbarSlider.activeBackground": "#B4A89599",
// ========== 列表和树视图 ==========
"list.activeSelectionBackground": "#E8E4DD",
"list.activeSelectionForeground": "#333333",
"list.inactiveSelectionBackground": "#F0EDE8",
"list.hoverBackground": "#F5F1EB",
"list.focusBackground": "#E8E4DD",
"list.focusForeground": "#333333",
"tree.indentGuidesStroke": "#E8E4DD",
// ========== 通知和消息 ==========
"notification.background": "#F7F2E7",
"notification.foreground": "#444444",
"notification.buttonBackground": "#D4C8B5",
"notification.buttonHoverBackground": "#C4B8A5",
"notification.buttonForeground": "#333333",
"notification.infoBackground": "#E8F0E8",
"notification.warningBackground": "#F8F0E8",
"notification.errorBackground": "#F8E8E8",
// ========== 其他界面元素 ==========
"focusBorder": "#D4C8B5",
"contrastBorder": "#E8E4DD",
"widget.shadow": "#E8E4DD80",
"badge.background": "#D4C8B5",
"badge.foreground": "#333333",
"progressBar.background": "#D4C8B5",
// ========== 终端 ==========
"terminal.background": "#FAF9F6",
"terminal.foreground": "#333333",
"terminalCursor.background": "#333333",
"terminalCursor.foreground": "#333333",
"terminal.ansiBlack": "#333333",
"terminal.ansiWhite": "#FAF9F6",
"terminal.selectionBackground": "#E8E4DD"
},
"workbench.colorTheme": "Solarized Light",
// ====== 格式化相关 ======
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
// ====== Prettier 配置(满足您的格式化规则) ======
"prettier.semi": true, // 1. 有分号
"prettier.trailingComma": "none", // 2. 无尾随逗号
"prettier.arrowParens": "avoid", // 3. 精简箭头函数(单参数无括号)
"prettier.singleQuote": true, // 4. JS 单引号
"prettier.jsxSingleQuote": false, // 5. JSX 双引号
"prettier.tabWidth": 2, // 6. 2 空格缩进
"prettier.useTabs": false, // 6. 不使用 Tab
"prettier.endOfLine": "lf", // 7. LF 换行符
"prettier.printWidth": 100, // 8. 每行最多 100 字符
// ====== 语言特定配置 ======
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode", // 统一使用 Prettier
"editor.tabSize": 2
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2
},
// ====== 代码编辑体验 ======
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.detectIndentation": false,
"editor.wordWrap": "off",
"editor.renderWhitespace": "selection",
"editor.rulers": [100], // 显示 100 字符参考线
// ====== ESLint 配置 ======
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"eslint.alwaysShowStatus": true,
"eslint.codeActionsOnSave.mode": "problems",
// ====== 文件保存 ======
"files.autoSave": "onFocusChange",
"files.eol": "\n", // 7. LF 换行符
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
// ====== 额外建议:更好地与 ESLint 集成 ======
"prettier.eslintIntegration": false, // Prettier 3.x 已移除,使用下面配置
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit" // 如果需要样式检查
},
"files.associations": {
"*.css": "tailwindcss"
},
"tailwindCSS.classAttributes": ["class", "className", "headerClassName"]
}
通过统一VS Code的setting.json来实现项目统一格式化的目的。在项目中没有使用Prettier包配置时,VS Code的setting会生效。
三、项目中使用Prettier(推荐)
1、安装Prettier依赖
bash
# 安装 Prettier 作为开发依赖
npm install --save-dev prettier
# 或使用 yarn
yarn add --dev prettier
2、创建.prettierrc.cjs文件
javascript
/** @type {import('prettier').Config} */
module.exports = {
// 基础风格
semi: true, // 有分号
trailingComma: 'none', // 不要尾随逗号
singleQuote: true, // 使用单引号,少按一次shift键
// 箭头函数
arrowParens: 'avoid', // 单参数不要括号,多参数保留
// 代码布局
printWidth: 100, // 每行最多100字符
tabWidth: 2, // 缩进2个空格
useTabs: false, // 用空格不是Tab
// 括号处理
bracketSpacing: true, // 对象括号内加空格 { key: value }
bracketSameLine: true, // JSX结束标签换行
// JSX特殊设置
jsxSingleQuote: false, // JSX属性用双引号 <div className="test">
// 其他
endOfLine: 'lf', // 统一换行符(Linux/macOS风格)
quoteProps: 'as-needed', // 只有必要时给属性加引号
proseWrap: 'preserve', // Markdown文本保持原样
// Next.js 相关扩展配置
overrides: [
{
files: '*.{js,jsx,ts,tsx}',
options: {
// React/Next.js 相关优化
parser: 'typescript',
// 确保 JSX 属性合理换行
jsxBracketSameLine: false,
// 处理长链式调用
singleAttributePerLine: false
}
},
{
files: '*.{css,scss}',
options: {
parser: 'css',
singleQuote: true
}
},
{
files: '*.json',
options: {
parser: 'json',
trailingComma: 'none'
}
},
{
files: '*.md',
options: {
parser: 'markdown',
proseWrap: 'preserve' // Markdown 文本保持原样
}
}
],
// 插件配置(如果有的话)
// plugins: ['prettier-plugin-tailwindcss'],
// 插件相关配置示例
/*
tailwindConfig: './tailwind.config.js',
tailwindFunctions: ['clsx', 'cn', 'tw'],
*/
// 格式化忽略的文件模式(也可以在 .prettierignore 中配置)
ignorePath: '.prettierignore'
};
3、创建.prettierignore文件
javascript
# 忽略文件
.next
node_modules
dist
build
out
public
coverage
*.log
.env*
*.local
.DS_Store
.vscode
.idea
4、有ESLint文件可以进行配置
javascript
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended' // 必须放在最后,关闭冲突规则
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: ['react', '@typescript-eslint'],
settings: {
react: {
version: 'detect'
}
},
rules: {
// === 匹配你的 Prettier 偏好 ===
semi: ['error', 'always'], // ✓ 改为有分号
'comma-dangle': ['error', 'never'], // 无尾随逗号
'arrow-parens': ['error', 'as-needed'], // 箭头函数括号精简
// === React 规则 ===
'react/react-in-jsx-scope': 'off', // React 17+ 不需要引入
'react/prop-types': 'off', // TypeScript 项目不需要
// === 代码质量 ===
'no-console': 'warn',
'no-unused-vars': 'off', // 使用 TypeScript 的规则
'@typescript-eslint/no-unused-vars': ['error'],
// === 简化规则 ===
quotes: ['error', 'single'], // 单引号
'jsx-quotes': ['error', 'prefer-double'] // JSX 双引号
}
};
5、在package.json中加入命令
bash
"format": "prettier --write 'src/**/*.{js,jsx,ts,tsx}'"
路径名称可以按照项目实际进行调整。
执行格式化脚本:
bash
yarn run format
四、格式化
1、格式化说明
-
有分号 - 语句结尾加分号
-
无尾随逗号 - 对象/数组最后一项后不加逗号
-
精简箭头函数 - 单参数无括号,多参数保留括号
-
JS 单引号 - JavaScript/TypeScript 代码用单引号
-
JSX 双引号 - JSX 属性值用双引号
-
2 空格缩进 - 使用空格缩进,不用 Tab
-
换行符统一 - 使用 LF 换行符
-
代码行限制 - 每行最多 100 字符
2、格式化优先级
优先级顺序(Prettier 从高到低):
-
本地
.prettierrc*配置文件 -
package.json中的prettier字段 -
VS Code 的
prettier.*设置 -
Prettier 默认值
3、格式化案例
javascript
/ ====== JavaScript/TypeScript 部分 ======
// 函数定义 - 单参数无括号
const getUser = id => {
return { id, name: '张三' };
};
// 多参数有括号
const addUser = (name, age) => ({
name,
age,
createdAt: new Date()
});
// 数组操作
const users = [
{ id: 1, name: '李四' },
{ id: 2, name: '王五' }
];
const activeUsers = users
.filter(user => user.id > 0)
.map(user => ({
...user,
status: 'active'
}));
// 对象定义 - 无尾随逗号
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000,
retries: 3
};
// ====== React 组件部分 ======
import React, { useState } from 'react';
const UserList = ({ users, onSelect }) => {
const [filter, setFilter] = useState('');
// 事件处理 - 单参数无括号
const handleClick = userId => {
onSelect(userId);
};
const handleChange = e => {
setFilter(e.target.value);
};
const filteredUsers = users.filter(user => user.name.includes(filter));
return (
<div className="user-list">
<input type="text" value={filter} onChange={handleChange} placeholder="搜索用户" />
<ul>
{filteredUsers.map(user => (
<li key={user.id}>
<span>{user.name}</span>
<button onClick={() => handleClick(user.id)}>选择</button>
</li>
))}
</ul>
</div>
);
};
// ====== 工具函数部分 ======
const utils = {
// 单参数无括号
formatDate: date => new Date(date).toLocaleDateString(),
// 多参数有括号
debounce: (fn, delay) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
};
// ====== 类定义部分 ======
class ApiClient {
constructor(baseURL) {
this.baseURL = baseURL;
}
// 单参数无括号
get = async path => {
const response = await fetch(`${this.baseURL}${path}`);
return response.json();
};
// 多参数有括号
post = async (path, data) => {
const response = await fetch(`${this.baseURL}${path}`, {
method: 'POST',
body: JSON.stringify(data)
});
return response.json();
};
}
// ====== 导出部分 ======
export { getUser, addUser };
export default UserList;
以上就是项目统一格式化的全部内容!