Vue3 代码风格工具集成

目录
前言
规范化的前端项目不仅能够提高代码质量,还能显著提升团队协作效率。本文将详细介绍如何基于Vue 3搭建一套完整的项目规范,涵盖代码风格、提交规范、编辑器配置等各个方面,团队可以直接参考并应用到自己的项目中。
包管理器选择
本项目统一使用pnpm作为包管理工具,推荐最新版本为10.12.14。
# 安装pnpm
npm install -g pnpm
# 创建项目
pnpm create vue@latest my-project
cd my-project
# 安装依赖
pnpm install
在项目根目录创建.npmrc
文件,配置npm镜像源:
registry=https://registry.npmmirror.com
strict-peer-dependencies=false
代码质量工具配置
ESLint配置
ESLint@9采用了新的扁平化配置方式,我们使用eslint.config.mjs
文件进行配置。
首先安装相关依赖:
pnpm add -D eslint @eslint/js globals eslint-config-prettier eslint-plugin-import-x eslint-plugin-prettier eslint-plugin-vue typescript-eslint
创建eslint.config.mjs
文件:
import js from '@eslint/js'
import globals from 'globals'
import eslintConfigPrettier from 'eslint-config-prettier'
import eslintPluginImportX from 'eslint-plugin-import-x'
import eslintPluginPrettier from 'eslint-plugin-prettier/recommended'
import eslintPluginVue from 'eslint-plugin-vue'
import typescriptEslint from 'typescript-eslint'
import { readFileSync } from 'node:fs'
// 导入自动导入的ESLint配置
const eslintrcAutoImport = JSON.parse(readFileSync(new URL('./.eslintrc-auto-import.json', import.meta.url)))
// TypeScript ESLint配置
const tsEslint = typescriptEslint.config(...typescriptEslint.configs.recommended).map((config) => ({
...config,
languageOptions: {
...config.languageOptions,
parserOptions: {
parser: '@typescript-eslint/parser'
}
}
}))
// Vue ESLint配置
const vueEslint = eslintPluginVue.configs['flat/recommended']
// 忽略的文件
const ignores = ['node_modules/', 'dist/', 'public/', 'src/assets/', '*.d.ts', '*.jpg', '*.jpeg', '*.png', '*.gif']
// 通用全局变量
const commonGlobals = { ...globals.browser, ...globals.node }
export default [
{
ignores,
plugins: {
'import-x': eslintPluginImportX
},
languageOptions: {
globals: commonGlobals
}
},
...tsEslint,
...vueEslint,
js.configs.recommended,
{
...eslintPluginPrettier,
rules: {
...eslintPluginPrettier.rules,
...eslintConfigPrettier.rules
}
},
{
files: ['src/**/*.{js,ts,jsx,tsx,vue}'],
rules: {
// Vue相关规则
'vue/v-on-event-hyphenation': [
'warn',
'always',
{
autofix: true
}
],
'vue/html-self-closing': [
'warn',
{
html: {
void: 'any',
normal: 'always',
component: 'always'
},
svg: 'always',
math: 'always'
}
],
'vue/attribute-hyphenation': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/multi-word-component-names': 'off',
// TypeScript规则
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }],
// 通用规则
'array-callback-return': 'error',
'sort-imports': 'off',
// 导入规则
'import-x/order': [
'error',
{
groups: ['external', 'builtin', 'internal', 'type', 'parent', 'object', 'sibling', 'index']
}
],
'import-x/no-cycle': 'error',
'import-x/no-self-import': 'error',
// 异步规则
'no-async-promise-executor': 'warn',
// Vue组件规则
'vue/component-options-name-casing': ['warn', 'PascalCase'],
'vue/component-name-in-template-casing': [
'warn',
'PascalCase',
{
registeredComponentsOnly: false,
ignores: []
}
],
'vue/component-api-style': ['error', ['script-setup', 'composition']],
'vue/define-macros-order': ['error', { order: ['defineOptions', 'defineProps', 'defineEmits', 'defineSlots'] }],
'vue/custom-event-name-casing': [
'warn',
'kebab-case',
{
ignores: []
}
],
'vue/define-emits-declaration': ['warn', 'type-based'],
'vue/define-props-declaration': ['warn', 'type-based'],
'vue/slot-name-casing': ['warn', 'camelCase']
},
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parserOptions: {
parser: typescriptEslint.parser,
ecmaFeatures: {
jsx: true
}
},
...eslintrcAutoImport // 合并自动导入的全局变量
}
}
]
Prettier配置
安装Prettier相关依赖:
pnpm add -D prettier eslint-plugin-prettier eslint-config-prettier
创建.prettierrc.js
文件:
export default {
printWidth: 120, // 一行的字符数,超过会自动换行
singleAttributePerLine: false, // 每行强制换行,只能使用单个属性
tabWidth: 2, // 一个tab代表几个空格
useTabs: false, // 是否使用tab进行缩进
singleQuote: true, // 使用单引号而非双引号
semi: false, // 行尾不使用分号
trailingComma: 'none', // 不使用尾逗号
bracketSpacing: true, // 对象大括号直接是否有空格,例如 { a: 1 }
endOfLine: 'auto',
jsxBracketSameLine: false, // 在jsx中 '>' 是否单独放一行
arrowParens: 'always', // 箭头函数参数总是使用括号
bracketSameLine: true // 多行HTML元素的'>'放在最后一行的末尾,而不是另起一行
}
Stylelint配置
安装Stylelint相关依赖:
pnpm add -D stylelint stylelint-config-html stylelint-config-prettier stylelint-config-recommended-scss stylelint-config-standard stylelint-order stylelint-prettier prettier-stylelint stylelint-config-recess-order stylelint-config-recommended-vue stylelint-config-standard-scss stylelint-scss postcss postcss-html
创建.stylelintrc.js
文件:
export default {
root: true,
defaultSeverity: 'warning',
extends: ['stylelint-config-recess-order', 'stylelint-config-standard-scss', 'stylelint-config-recommended-vue/scss'],
plugins: ['stylelint-scss'],
ignoreFiles: ['**/*', '!src/**/*', 'src/**/*.{js,jsx,ts,tsx}'],
rules: {
'scss/at-rule-no-unknown': true,
'function-no-unknown': null,
'value-no-vendor-prefix': null,
'property-no-vendor-prefix': null,
'selector-class-pattern':
'^[a-z]([a-z0-9-]+)?(__([a-z0-9]+-?)+)?(__([a-z0-9]+-?)+)?(--([a-z0-9]+-?)+){0,2}$|^Mui.*$|^([a-z][a-z0-9]*)(_[a-z0-9]+)*$',
'font-family-no-missing-generic-family-keyword': null,
'scss/dollar-variable-pattern': null,
'block-no-empty': null,
'no-empty-source': null,
'property-no-unknown': null,
'no-descending-specificity': null,
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['export', 'deep', 'global', 'import']
}
],
'rule-empty-line-before': [
'always',
{
except: ['first-nested'],
ignore: ['after-comment']
}
],
'custom-property-empty-line-before': [
'always',
{
except: ['after-custom-property', 'first-nested']
}
],
'declaration-empty-line-before': [
'always',
{
except: ['after-declaration', 'first-nested']
}
],
// 忽略特定at规则
'at-rule-no-unknown': [
true,
{
ignoreAtRules: [
'tailwind',
'apply',
'variants',
'responsive',
'screen',
'function',
'if',
'each',
'include',
'mixin',
'return',
'use'
]
}
],
'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }],
'order/order': ['custom-properties', 'declarations'],
'order/properties-order': ['width', 'height']
},
overrides: [
{
files: ['src/**/*.vue'],
extends: [
'stylelint-config-recess-order',
'stylelint-config-standard-scss',
'stylelint-config-recommended-vue/scss'
],
plugins: ['stylelint-scss'],
rules: {
'declaration-property-value-no-unknown': null,
'scss/dollar-variable-pattern': null,
'block-no-empty': null,
'comment-empty-line-before': null,
'no-empty-source': null,
'property-no-unknown': null,
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['deep', 'v-deep']
}
]
}
}
]
}
自动导入适配
安装自动导入相关依赖:
pnpm add -D unplugin-auto-import
在vite.config.ts
中配置:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
plugins: [
vue(),
AutoImport({
// 自动导入Vue相关API
imports: ['vue', 'vue-router', 'pinia'],
// 生成对应的d.ts文件
dts: true,
// 生成ESLint配置文件
eslintrc: {
enabled: true, // 默认false
filepath: './.eslintrc-auto-import.json',
globalsPropValue: true
}
})
]
})
Git工作流规范
Husky配置
安装Husky:
pnpm add -D husky
pnpm exec husky init
lint-staged配置
安装lint-staged:
pnpm add -D lint-staged
创建lint-staged.config.js
文件:
export default {
'*.{js,jsx,ts,tsx,vue}': ['eslint --fix'],
'*.vue': ['eslint --fix', 'stylelint --fix'],
'*.{scss,less,css,stylus,styl}': ['stylelint --fix'],
'*.{js,jsx,ts,tsx,vue,css,scss,less,md,json}': ['prettier --write']
}
配置Husky的pre-commit钩子,创建.husky/pre-commit
文件:
#!/usr/bin/env sh
pnpm exec lint-staged
commitlint配置
安装commitlint相关依赖:
pnpm add -D @commitlint/cli @commitlint/config-conventional
创建.commitlintrc.js
文件:
export default {
extends: ['@commitlint/config-conventional']
}
配置Husky的commit-msg钩子,创建.husky/commit-msg
文件:
#!/usr/bin/env sh
pnpm exec commitlint -e
确保脚本有执行权限:
chmod +x .husky/pre-commit
chmod +x .husky/commit-msg
编辑器配置
editorconfig配置
在项目根目录创建.editorconfig
文件:
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
charset = utf-8
# 设置space使用index_size, 设置为tab使用tab_width
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
vscode配置
创建.vscode/settings.json
文件:
{
"prettier.prettierPath": "./node_modules/prettier",
"prettier.requireConfig": true,
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.dragAndDrop": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit"
},
"stylelint.enable": true,
"stylelint.validate": ["css", "less", "scss", "vue"],
"eslint.enable": true,
"eslint.format.enable": true,
"eslint.useFlatConfig": true,
"eslint.codeActionsOnSave.mode": "problems",
"eslint.validate": ["typescript", "javascript", "javascript react", "typescript react", "vue"],
"[vue]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
创建.vscode/extensions.json
文件,推荐安装的VS Code扩展:
{
"recommendations": [
"dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint",
"esbenp.prettier-vscode",
"gencer.html-slim-scss-css-class-completion",
"syler.sass-indented",
"eamodio.gitlens",
"donjayamanne.githistory",
"editorconfig.editorconfig",
"vue.volar"
]
}
TypeScript配置
创建tsconfig.json
文件:
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"types": ["vite/client"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
创建tsconfig.node.json
文件:
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
项目文档
创建一个高质量的README.md
文件对项目的长期维护至关重要,应包含以下内容:
- 项目名称和简介
- 技术栈说明
- 目录结构
- 安装和使用指南
- 开发规范
- 常见问题
示例见文章最后的完整配置文件示例部分。
最佳实践建议
统一环境:
- 使用统一的Node.js版本
- 使用统一的包管理器版本
- 配置
.nvmrc
文件指定Node版本
代码规范:
- 组件命名使用PascalCase
- CSS类名使用kebab-case
- 文件名规范(如组件文件使用PascalCase)
分支管理:
- 采用标准的Git工作流,如GitFlow或GitHub Flow
- 主分支保护,通过PR合并代码
构建优化:
- 代码拆分和懒加载
- 图片优化
- 缓存策略
项目文档:
- 保持文档更新
- 包含常见问题(FAQ)
- 编写组件使用示例
完整配置文件示例
package.json 核心配置
{
"name": "vue3-project",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"eslint": "eslint --config eslint.config.mjs . --ext .vue,.js,.ts,.jsx,.tsx,.mjs,.cjs --cache --cache-location node_modules/.cache/eslint/",
"eslint:fix": "eslint --config eslint.config.mjs . --ext .vue,.js,.ts,.jsx,.tsx,.mjs,.cjs --fix --cache --cache-location node_modules/.cache/eslint/",
"stylelint": "stylelint --cache \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
"stylelint:fix": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
"prettier": "prettier --check .",
"prettier:fix": "prettier --write .",
"lint:all": "npm run eslint:fix && npm run stylelint:fix && npm run prettier:fix",
"prepare": "husky",
"type-check": "vue-tsc --noEmit"
},
"dependencies": {
"vue": "^3.4.21",
"vue-router": "^4.3.0",
"pinia": "^2.2.2"
},
"devDependencies": {
"@commitlint/cli": "^19.2.1",
"@commitlint/config-conventional": "^19.2.1",
"@eslint/js": "^9.29.0",
"@types/node": "^20.12.10",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-vue": "^5.0.5",
"eslint": "^9.29.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-prettier": "^5.5.0",
"eslint-plugin-vue": "^9.33.0",
"globals": "^16.2.0",
"husky": "^9.1.7",
"lint-staged": "^15.5.2",
"postcss": "^8.4.49",
"prettier": "^3.5.3",
"sass": "^1.69.7",
"stylelint": "^16.20.0",
"stylelint-config-prettier": "^9.0.5",
"stylelint-config-recommended-scss": "^14.1.0",
"stylelint-config-standard": "^36.0.1",
"stylelint-config-recess-order": "6.0.0",
"stylelint-config-recommended-vue": "^1.6.0",
"stylelint-config-standard-scss": "14.0.0",
"stylelint-scss": "^6.11.1",
"typescript": "^5.8.3",
"typescript-eslint": "^8.35.1",
"unplugin-auto-import": "^0.18.3",
"vite": "^4.5.14",
"vue-tsc": "^2.0.6"
}
}
示例README.md
# Vue 3 项目模板
<div align="center">
[](https://vuejs.org/)
[](https://vitejs.dev/)
[](https://pinia.vuejs.org/)
[](https://www.typescriptlang.org/)
[](https://nodejs.org/)
[](#许可证)
</div>
## 📋 目录
- [项目简介](#项目简介)
- [功能特点](#功能特点)
- [技术栈](#技术栈)
- [快速开始](#快速开始)
- [环境要求](#环境要求)
- [安装与使用](#安装与使用)
- [可用脚本](#可用脚本)
- [项目结构](#项目结构)
- [开发规范](#开发规范)
- [代码风格](#代码风格)
- [分支管理](#分支管理)
- [提交规范](#提交规范)
- [许可证](#许可证)
## 项目简介
项目简介内容
## 功能特点
- **特点1**:描述
- **特点2**:描述
- **特点3**:描述
## 技术栈
- **前端框架**:Vue 3.4.x
- **构建工具**:Vite 4.5.x
- **状态管理**:Pinia 2.2.x
- **路由管理**:Vue Router 4.3.x
- **CSS预处理器**:Sass 1.69.x
- **编程语言**:TypeScript 5.8.x
- **HTTP客户端**:Axios 1.7.x
- **代码规范**:ESLint 9.29.x + Prettier 3.5.x + Stylelint 16.20.x
- **Git钩子**:Husky 9.1.x + Lint-staged 15.5.x
## 快速开始
### 环境要求
- **Node.js**: >= 18.0.0
- **包管理器**: pnpm >= 10.12.14
- **浏览器兼容**: 支持现代浏览器,不兼容IE
### 安装与使用
1. **克隆项目**
```bash
git clone [项目仓库地址]
cd [项目名称]
```
2. **安装依赖**
```bash
pnpm install
```
3. **启动开发服务器**
```bash
pnpm dev
```
4. **构建项目**
```bash
pnpm build
```
### 可用脚本
| 命令 | 描述 |
| -------------------- | --------------------------------- |
| `pnpm dev` | 启动开发服务器 |
| `pnpm build` | 构建生产环境代码 |
| `pnpm preview` | 本地预览生产构建 |
| `pnpm eslint` | 检查JavaScript/TypeScript/Vue代码 |
| `pnpm eslint:fix` | 自动修复ESLint问题 |
| `pnpm stylelint` | 检查CSS/SCSS样式 |
| `pnpm stylelint:fix` | 自动修复Stylelint问题 |
| `pnpm prettier:fix` | 格式化所有文件 |
| `pnpm lint:all` | 执行所有代码检查并自动修复 |
| `pnpm type-check` | 执行TypeScript类型检查 |
## 项目结构
```sh
vue3-project
├─ public // 公共资源,可直接访问
├─ src // 项目核心文件夹
│ ├─ assets // 公共资源文件
│ │ ├─ icons // 图标资源
│ │ ├─ images // 图片资源
│ │ └─ styles // 全局样式
│ │ ├─ variables.scss // SCSS变量
│ │ ├─ mixins.scss // SCSS混合
│ │ └─ global.scss // 全局样式
│ ├─ components // 公共组件
│ ├─ composables // 组合式函数
│ ├─ config // 公共配置
│ ├─ directives // 全局指令
│ ├─ hooks // 自定义钩子
│ ├─ pages // 页面组件
│ ├─ router // 路由配置
│ ├─ services // API服务
│ ├─ stores // 状态管理
│ ├─ types // TypeScript类型
│ ├─ utils // 工具函数
│ ├─ App.vue // 根组件
│ ├─ main.ts // 入口文件
├─ eslint.config.mjs // ESLint配置
├─ .prettierrc.js // Prettier配置
├─ .stylelintrc.js // Stylelint配置
├─ tsconfig.json // TypeScript配置
├─ vite.config.ts // Vite配置
└─ package.json // 项目配置和依赖
```
## 开发规范
### 代码风格
项目已配置ESLint、Prettier和Stylelint来保证代码质量和一致性:
- 提交代码前会自动检查和格式化
- 可以手动执行 `pnpm lint:all` 检查并修复所有问题
- 组件命名使用PascalCase
- CSS类名使用kebab-case
- 组件目录结构保持一致
### 分支管理
项目采用以下分支管理策略:
- `main`或`master`: 稳定的生产环境代码
- `develop`: 测试环境分支,用于集成测试
- `feature/*`: 功能开发分支,从主分支创建
- `release/*`: 发布准备分支,多个团队同时上线时使用的公共分支
### 提交规范
提交信息格式:`类型(作用域): 描述`
类型包括:
- `feat`: 新功能
- `fix`: 修复bug
- `docs`: 文档变更
- `style`: 代码格式调整
- `refactor`: 代码重构
- `perf`: 性能优化
- `test`: 测试相关
- `chore`: 构建过程或辅助工具变动
示例:
- `feat(chat): 添加聊天记录导出功能`
- `fix(upload): 修复图片上传失败问题`
## 许可证
[MIT License](./LICENSE)
以上配置可作为Vue 3项目的基础规范,团队可以根据自身需求进行适当调整和扩展。通过这套规范,团队成员可以快速上手,减少代码冲突,提高开发效率,保证代码质量。