
Vue3 + Vite 中级编程总结二
2025年1月10日...大约 7 分钟
Vue3 + Vite 中级编程总结二
开发环境
$ node -v
v22.14.0
$ vue -V
@vue/cli 5.0.8
$ npm -v
10.9.2
$ pnpm -v
10.4.1
项目初始化
pnpm create vite
配置文档常用配置
package.json 配置文档
"scripts": {
"dev": "vite --open",
"build": "vue-tsc -b && vite build",
"preview": "vite preview",
"lint": "eslint --ext .ts,.tsx,.vue src",
"lint:fix": "eslint --ext .ts,.tsx,.vue src --fix"
},
eslint.config.js 配置文档
vscode 插件安装
Eslint: Microsoft microsoft.com 语法错误检查
Prettier-Code formatter: Prettier prettier.io 通用格式化工具
Stylelint: Stylelint stylelint.io css格式化工具
UnoCss: Anthony Fu
Vue-Official: Vue vuejs.org vue语法工具
PostCss Language Support: csstools
安装 eslint 并创建 eslint.config.js 文档
D:\vue3_admin_template\project>pnpm install eslint -D //安装eslint
D:\vue3_admin_template\project>npx eslint --init //生成配置文件
You can also run this command directly using 'npm init @eslint/config@latest'.
> project@0.0.0 npx
> create-config
@eslint/create-config: v1.8.1
√ What do you want to lint? · javascript
√ How would you like to use ESLint? · problems
√ What type of modules does your project use? · esm
√ Which framework does your project use? · vue
√ Does your project use TypeScript? · no / yes
√ Where does your code run? · browser
The config that you've selected requires the following dependencies:
eslint, @eslint/js, globals, typescript-eslint, eslint-plugin-vue
√ Would you like to install them now? · No / Yes
√ Which package manager do you want to use? · pnpm
☕️Installing...
Already up to date
Progress: resolved 216, reused 172, downloaded 0, added 0, done
dependencies:
+ vue 3.5.13
devDependencies:
+ @eslint/js 9.25.1
+ @vitejs/plugin-vue 5.2.3
+ @vue/tsconfig 0.7.0
+ eslint 9.25.1
+ eslint-plugin-vue 10.0.1
+ globals 16.0.0
+ typescript 5.7.3
+ typescript-eslint 8.31.1
+ vite 6.3.4
+ vue-tsc 2.2.10
Done in 1.2s using pnpm v10.4.1
Successfully created D:\vue3_admin_template\project\eslint.config.js file.
eslint.config.js 初始文档
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import pluginVue from "eslint-plugin-vue";
import { defineConfig } from "eslint/config";
export default defineConfig([
{
files: ["**/*.{js,mjs,cjs,ts,vue}"],
plugins: { js },
extends: ["js/recommended"],
},
{
files: ["**/*.{js,mjs,cjs,ts,vue}"],
languageOptions: { globals: globals.browser },
},
tseslint.configs.recommended,
pluginVue.configs["flat/essential"],
{
files: ["**/*.vue"],
languageOptions: { parserOptions: { parser: tseslint.parser } },
},
{
rules: {
"no-unused-vars": "warn",
"no-undef": "warn",
},
},
]);
配置后的文档
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import vueParser from "vue-eslint-parser";
import pluginVue from "eslint-plugin-vue";
import { defineConfig } from "eslint/config";
export default defineConfig([
// ==================== JavaScript 基础配置 ====================
{
files: ["**/*.js", "**/*.cjs"],
...js.configs.recommended,
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
globals: {
...globals.browser,
...globals.node,
...globals.es2021,
},
},
rules: {
// 基本规则
"no-var": "error",
"prefer-const": ["error", { destructuring: "all" }],
eqeqeq: ["error", "always", { null: "ignore" }],
// 代码风格
indent: ["error", 2, { SwitchCase: 1 }],
quotes: ["error", "single", { avoidEscape: true }],
semi: ["error", "never"],
"comma-dangle": ["error", "always-multiline"],
"object-curly-spacing": ["error", "always"],
"array-bracket-spacing": ["error", "never"],
// 最佳实践
"no-multi-spaces": "error",
"no-multiple-empty-lines": ["error", { max: 1 }],
"no-trailing-spaces": "error",
"no-unreachable": "error",
"no-unsafe-optional-chaining": "error",
// 变量相关
"no-unused-vars": ["error", { args: "none", varsIgnorePattern: "^_" }],
"no-shadow": ["error", { hoist: "functions" }],
// 异步代码
"no-await-in-loop": "warn",
"require-atomic-updates": "error",
},
},
// ==================== TypeScript 配置 ====================
{
files: ["**/*.ts", "**/*.tsx"],
...tseslint.configs.recommended,
languageOptions: {
parser: tseslint.parser,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
project: "./tsconfig.json",
warnOnUnsupportedTypeScriptVersion: true,
},
globals: {
...globals.browser,
...globals.es2021,
},
},
rules: {
// TypeScript 核心规则
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": ["error", { default: "array-simple" }],
"@typescript-eslint/ban-types": [
"error",
{
types: {
Object: "Avoid using the `Object` type. Did you mean `object`?",
Function:
"Avoid using the `Function` type. Prefer a specific function type.",
Boolean: "Avoid using the `Boolean` type. Did you mean `boolean`?",
Number: "Avoid using the `Number` type. Did you mean `number`?",
String: "Avoid using the `String` type. Did you mean `string`?",
},
},
],
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/consistent-type-definitions": ["error", "interface"],
"@typescript-eslint/consistent-type-imports": [
"error",
{ prefer: "type-imports", disallowTypeAnnotations: false },
],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/member-delimiter-style": [
"error",
{
multiline: { delimiter: "none", requireLast: false },
singleline: { delimiter: "semi", requireLast: false },
},
],
"@typescript-eslint/no-dynamic-delete": "error",
"@typescript-eslint/no-empty-interface": [
"error",
{ allowSingleExtends: true },
],
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/no-this-alias": "error",
"@typescript-eslint/no-unnecessary-type-constraint": "error",
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-await": "warn",
"@typescript-eslint/restrict-plus-operands": "error",
"@typescript-eslint/triple-slash-reference": "error",
"@typescript-eslint/unified-signatures": "error",
// 覆盖基础 ESLint 规则以支持 TS
"no-unused-vars": "off",
"no-shadow": "off",
"@typescript-eslint/no-shadow": "error",
semi: "off",
"@typescript-eslint/semi": ["error", "never"],
quotes: "off",
"@typescript-eslint/quotes": ["error", "single"],
indent: "off",
"@typescript-eslint/indent": ["error", 2],
},
},
// ==================== Vue 配置 ====================
{
files: ["**/*.vue"],
languageOptions: {
parser: vueParser,
parserOptions: {
parser: tseslint.parser,
extraFileExtensions: [".vue"],
ecmaVersion: "latest",
sourceType: "module",
project: "./tsconfig.json",
},
globals: {
...globals.browser,
...globals.es2021,
},
},
plugins: {
vue: pluginVue,
},
rules: {
...pluginVue.configs["vue3-recommended"].rules,
// Vue 特定规则覆盖
"vue/multi-word-component-names": "warn",
"vue/no-setup-props-destructure": "off",
"vue/script-setup-uses-vars": "error",
"vue/component-api-style": ["error", ["script-setup"]],
"vue/component-tags-order": [
"error",
{
order: ["script", "template", "style"],
},
],
"vue/html-self-closing": [
"error",
{
html: {
void: "always",
normal: "always",
component: "always",
},
svg: "always",
math: "always",
},
],
"vue/max-attributes-per-line": [
"error",
{
singleline: { max: 3 },
multiline: { max: 1 },
},
],
},
},
// ==================== 通用规则覆盖 ====================
{
rules: {
// 开发环境规则
"no-console": process.env.NODE_ENV === "production" ? "error" : "warn",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "warn",
// 适用于所有文件类型的规则
"arrow-parens": ["error", "always"],
"prefer-arrow-callback": "warn",
"dot-notation": "error",
"no-param-reassign": "error",
},
},
// ==================== 测试文件配置 ====================
{
files: ["**/*.spec.ts", "**/*.test.ts", "**/__tests__/**/*.ts"],
languageOptions: {
globals: {
...globals.jest,
},
},
rules: {
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-empty-function": "off",
"no-console": "off",
},
},
]);
配置说明:
基础配置:
使用 @eslint/js 提供的推荐规则
使用 typescript-eslint 的推荐规则
Vue 特定配置:
使用 vue-eslint-parser 解析 .vue 文件
启用 vue3-recommended 规则集
添加了一些 Vue 3 的最佳实践规则
通用规则:
严格的 TypeScript 类型检查
生产环境禁止 console/debugger
一致的代码风格(单引号、无分号等)
测试文件配置:
为测试文件添加了 Jest 全局变量
放宽了一些测试文件中的规则限制
使用建议:
将此文件保存为 eslint.config.js 在项目根目录
确保您的 package.json 中包含所有指定的依赖版本
在 vite.config.ts 中确保已正确配置 Vue 插件
这个配置遵循了 ESLint 新的扁平化配置格式,并针对 Vue 3 + TypeScript 项目进行了优化。您可以根据项目实际需求进一步调整规则。
配置亮点说明:
JavaScript 配置:
严格模式基础规则
现代 ES2021+ 语法支持
代码风格一致性规则(缩进、引号、分号等)
变量和异步代码最佳实践
TypeScript 配置:
完整的类型安全规则集
类型导入/导出的一致性
接口与类型别名的最佳实践
严格的 null/undefined 检查
Promise 处理规则
覆盖基础 ESLint 规则以支持 TypeScript 语法
与 Vue 的集成:
确保 TypeScript 解析器能正确处理 .vue 文件
保持与 vue-tsc 的类型检查一致
Vue 3 特有的组合式 API 规则
环境区分:
开发环境和生产环境不同的日志规则
测试文件专用的宽松规则
这个配置已经针对您提供的依赖版本进行了优化,特别是:
@typescript-eslint v8.31.1
eslint-plugin-vue v10.0.1
Vue 3.5.13 的特性支持
您可以根据项目实际需求调整规则严格程度,特别是 @typescript-eslint/no-explicit-any 和 @typescript-eslint/no-non-null-assertion 等规则。
手动创建.npmrc 文档在项目根目录下,确保 pnpm 以与 npm 更兼容的方式安装依赖,并且不太可能产生错误。
auto-install-peers=true
node-linker=hoisted
电商平台后台管理配置
import globals from "globals";
import js from "@eslint/js";
import ts from "typescript-eslint";
import vueParser from "vue-eslint-parser";
import vuePlugin from "eslint-plugin-vue";
import prettierConfig from "eslint-config-prettier";
import { defineConfig } from "eslint/config";
export default defineConfig([
// 基础环境配置
{
languageOptions: {
globals: {
...globals.browser,
...globals.es2021,
...globals.node,
...globals.jest,
},
},
},
// ESLint 推荐规则
js.configs.recommended,
// TypeScript 推荐规则
...ts.configs.recommended,
// Vue 基本规则
{
files: ["**/*.vue"],
languageOptions: {
parser: vueParser,
parserOptions: {
parser: ts.parser,
ecmaVersion: "latest",
sourceType: "module",
jsxPragma: "React",
ecmaFeatures: {
jsx: true,
},
},
},
plugins: {
vue: vuePlugin,
},
rules: {
...vuePlugin.configs["vue3-essential"].rules,
},
},
// Prettier 兼容配置
{
...prettierConfig,
rules: {
"prettier/prettier": "warn",
},
},
// 自定义规则覆盖
{
rules: {
// ESLint 基础规则
"no-var": "error",
"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 规则
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/prefer-ts-expect-error": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-namespace": "off",
"@typescript-eslint/semi": "off",
// Vue 规则
"vue/multi-word-component-names": "off",
"vue/script-setup-uses-vars": "error",
"vue/no-mutating-props": "off",
"vue/attribute-hyphenation": "off",
},
},
]);
vue3环境代码校验插件
pnpm install -D eslint-plugin-import eslint-plugin-vue eslint-plugin-node eslint-plugin-prettier eslint-config-prettier eslint-plugin-node @babel/eslint-parser
# 让所有与prettier规则存在冲突的eslint rules失效,并使用prettier进行代码检查
"eslint-config-prettier": "^10.1.2",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-node": "^11.1.0",
# 运行更漂亮的eslint,使prettier规则优先级更高,eslint优先级更低
"eslint-plugin-prettier": "^5.2.6",
# vue.js的eslint插件(查找vue语法错误,发现错误指令,查找违规风格指南)
"eslint-plugin-vue": "^10.0.1",
# 该解析器允许使用eslint校验所有babel 代码
"@babel/eslint-parser": "^7.27.0",