超级详细 最新 vite4+vue3+ts+element-plus+eslint-prettier 项目搭建流程

vite4+vue3+ts+element-plus 项目搭建流程

系列文章目录
【element-plus】 table表格每行圆角解决方案 element也通用
【Vue3+Vite+Ts+element-plus】使用tsx实现左侧栏菜单无限层级封装
超级详细GitBook和GitLab集成步骤【linux环境】

相关插件连接:
vite                         https://cn.vitejs.dev/guide/
vue                          https://cn.vuejs.org/
vue-router                   https://router.vuejs.org/zh/
vuex                         https://vuex.vuejs.org/zh/guide/
Pinia                        https://pinia.web3doc.top/

npm 包查询: https://www.npmjs.com

1、项目初始化

1.1、项目创建

执行以下代码将vite将会自动生成初始的 vite4+vue3+ts的项目模板,pnpm、npm、yarn 选择一种执行即可。我这里选择的是pnpm

注意: demo 为项目名称 可自定义, --template vue-ts 为创建vue3+ts的项目

pnpm create vite demo --template vue-ts
或
npm  create vite demo --template vue-ts
或
yarn create vite demo --template vue-ts

执行完成之后 将会出现以下代码

../pnpm/v3/tmp/dlx-13432                 |   +1 +
Packages are hard linked from the content-addressable store to the virtual store.
  Content-addressable store is at: D:\pnpm\v3
  Virtual store is at:             ../pnpm/v3/tmp/dlx-13432/node_modules/.pnpm
../pnpm/v3/tmp/dlx-13432                 | Progress: resolved 1, reused 1, downloaded 0, added 1, done

Scaffolding project in D:\test\zlkj\测试\demo...

Done. Now run:

  cd demo
  pnpm install
  pnpm run dev

接着执行 cd demo 进入项目

 cd demo

然后执行以下命令 初始化安装项目所需要的依赖包

 pnpm install

注意:如果是npm 则需要执行的是npm install ,如果是yarn 执行的 是 yarn install

1、接着我们将 src 下的 components 下的HelloWorld.vue 删除
2、然后在 src 新增 views 文件夹 
3、接着在 views 文件夹下新建 testView 文件夹
4、最后在 testView 下新建 testView.vue 文件

testView.vue 文件文件内容如下:


1.2、项目初始化配置

1.2.1、项目路径配置

我们需要安装和配置一些项目必须的东西, 首先对路径进行配置 我们需要安装

pnpm install @types/node --save-dev
pnpm install path

接着修改项目根目录下的 vite.config.ts 文件 如下:

import { ConfigEnv, UserConfig, defineConfig } from "vite";
import path, { resolve } from "path";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
  return {
    resolve: {
      //配置项目的绝对路径
      alias: {
        "@": resolve(__dirname, "src"), // 设置 @ 指向 /src 目录
      },
    },
    plugins: [vue()],
  };
});

更改完 vite.config.ts 文件 还需对根目录下的 tsconfig.json 进行配置 否则不生效 更改如下:

完整代码如下:

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "node",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",

    /* Linting */
    "strict": false,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "baseUrl": ".", // 用于设置解析非相对模块名称的基本目录,相对模块不会受到baseUrl的影响
    "paths": {
      // 用于设置模块名到基于baseUrl的路径映射
      "@/*": ["src/*"],
      "@api": ["src/api/api.ts"]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

配置完成 tsconfig.json 之后 还需要进行一步配置 因为vite中vue文件不是模块 所以必须将vue声明一下。

src文件夹下 新建 types 文件夹 该文件夹用于存放类型声明的**.d.ts**文件

接着在 types 文件夹 下 新建 env.d.ts 文件 内容如下

//.vue 文件声明
declare module "*.vue" {
  import type { DefineComponent } from "vue";
  const component: DefineComponent<{}, {}, any>;
  export default component;
}

最后将 src 下的 shims-vue.d.ts 也移动到 types 文件夹中 这样项目看起来更简洁

1.2.2、项目端口配置

因为vite创建项目后 默认启动是3000端口 ,但此端口有可能被占用导致运行启动报错

所以我们需要在项目根目录下的 vite.config.ts 中新增一下配置去自定义端口,完整代码如下:

import { ConfigEnv, UserConfig, defineConfig } from "vite";
import path, { resolve } from "path";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
  return {
    resolve: {
      //配置项目的绝对路径
      alias: {
        "@": resolve(__dirname, "src"), // 设置 @ 指向 /src 目录
      },
    },
    server: {
      port: 8818, //端口 自定义
      host: "0.0.0.0",
      cors: true, // 默认启用并允许任何源
      //代理
      proxy: {},
    },
    plugins: [vue()],
  };
});

1.2.3、项目运行环境区分

项目在本地运行和打包线上运行时 或者是测试环境时有些环境是不一样的,所以 vite 提供了一种方式让我们可以区分不同的环境来运行。

首先 在src目录下新增env 文件夹, 并在 env 文件夹下新增 .env.development.env.production 文件

.env.development 内容如下

## 开发环境配置	

## 本地运行路径 这个不能变
VITE_PUBLIC_PATH='./'

## 项目名称    
VITE_APP_BASE_NAME='项目'	

## 如需其它配置项可自定义   但必须是VITE_APP_开头

.env.production

## 生产环境配置	
## 本地运行路径 (无需变动)
VITE_PUBLIC_PATH='/'

## 项目名称  
VITE_APP_BASE_NAME='项目'	

## 如需其它配置项可自定义   但必须是VITE_APP_开头

请注意 VITE_PUBLIC_PATH 是区分本地环境 和 打包环境 请勿更改

新增完成之后 在根目录下的 package.json 中修改 scripts 的 dev 和 buid 如下:

 "scripts": {
    "dev": "vite  --mode development",
    "build": "vue-tsc --noEmit && vite build --mode production",
    .........
  }
  .....

作用:当运行 dev是 调用的是 .env.development 文件中的配置 当运行build 时调用的是 .env.production 的配置

最后更改 vite.config.ts 文件如下:

import { ConfigEnv, UserConfig, defineConfig, loadEnv } from "vite";
import path, { resolve } from "path";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
  const env = loadEnv(mode, process.cwd()); // 获取.env文件里定义的环境变量
  return {
    base: env.VITE_PUBLIC_PATH, // 开发公共基础路径
    resolve: {
      //配置项目的绝对路径
      alias: {
        "@": resolve(__dirname, "src"), // 设置 @ 指向 /src 目录
      },
    },
    server: {
      port: 8818, //端口
      host: "0.0.0.0",
      cors: true, // 默认启用并允许任何源
      //代理
      proxy: {},
    },
    plugins: [vue()],
  };
});

1.2.4、项目必要插件引入及安装

首先是自动导入相关插件的安装

pnpm  install  unplugin-vue-components unplugin-auto-import  unplugin-icons --save-dev
  • unplugin-vue-components 能在vue文件中自动引入无需手动引入
  • unplugin-auto-import 自动导入导入vue和vue-router 等组件的相关函数
  • unplugin-icons 图标自动导入

接着安装jsx、tsx的支持 如你的项目没用到则可无需安装 推荐安装一下

pnpm install @vitejs/plugin-vue-jsx --save-dev

安装完成之后需在vite.config.ts 中进行使用 代码如下:

import { ConfigEnv, UserConfig, defineConfig, loadEnv } from "vite";
import path, { resolve } from "path";
import Components from "unplugin-vue-components/vite";
import AutoImport from "unplugin-auto-import/vite";
import IconResolver from "unplugin-icons/resolver";
import vueJsx from "@vitejs/plugin-vue-jsx";
import Icons from "unplugin-icons/vite";
import vue from "@vitejs/plugin-vue";
const pathSrc = path.resolve(__dirname, "src");
// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
  const env = loadEnv(mode, process.cwd()); // 获取.env文件里定义的环境变量
  return {
    base: env.VITE_PUBLIC_PATH, // 开发公共基础路径
    resolve: {
      //配置项目的绝对路径
      alias: {
        "@": resolve(__dirname, "src"), // 设置 @ 指向 /src 目录
      },
    },
    server: {
      port: 8818, //端口
      host: "0.0.0.0",
      cors: true, // 默认启用并允许任何源
      //代理
      proxy: {},
    },
    plugins: [
      vue(),
      //自动导入components下的自定义组件
      Components({
        // dirs 指定组件所在位置,默认为 src/components
        // 可以让我们使用自己定义组件的时候免去 import 的麻烦
        dirs: ["src/components/", "src/layout"],
        // 配置需要将哪些后缀类型的文件进行自动按需引入,'vue'为默认值
        extensions: ["vue", "ts"],
        // 解析组件,这里以 Element Plus 为例
        resolvers: [],
        // 遍历子目录
        deep: true,
        dts: path.resolve(pathSrc, "types", "components.d.ts"), // 指定自动导入组件TS类型声明文件路径
      }),
      //自动导入组件
      AutoImport({
        imports: ["vue", "vuex", "vue-router"],
        dts: path.resolve(pathSrc, "types", "auto-imports.d.ts"), // 指定自动导入函数TS类型声明文件路径
        eslintrc: {
           // 一开始的时候设置为true 后面关闭就好 有更新再打开
          enabled: true,
          filepath: "./.eslintrc-auto-import.json",
          globalsPropValue: true,
        },
      }),
      //自动导入图标
      Icons({ scale: 1, defaultClass: "inline-block", autoInstall: true }),
      //vueJsx
      vueJsx({}),
    ],
  };
});

1.2.5、项目初始化样式更改

清空 src目录下的 style.css 文件内容 或者直接删除style.css 文件 并在main.ts去除import “./style.css”;

接着安装 normalize.css

pnpm install normalize.css

提示: normalize.css 只是一个很小的CSS文件,但它在默认的HTML元素样式上提供了跨浏览器的高度一致性。相比于传统的CSS reset,Normalize.css是一种现代的、为HTML5准备的优质替代方案。

并在src 目录下的 main.ts 进行引入

import { createApp } from 'vue';
import './style.css';
import './permission';
import App from './App.vue';
import 'normalize.css/normalize.css';

createApp(App).mount('#app');
1.2.6、初始化项目目录

最后在src 目录下新建一些必要目录

新建 api hooks stote style utils layout 文件夹

目录如下:

我们来解释一下这些目录都是用来干嘛的

|-node_modules       -- 所有的项目依赖包都放在这个目录下
|-public             -- 公共文件夹
---|favicon.ico      -- 网站的显示图标
---|index.html       -- 入口的html文件
|-src                -- 源文件目录,编写的代码基本都在这个目录下
---|api              -- axios请求 接口定义的存放地址  
---|assets           -- 放置静态文件的目录,比如logo.png就放在这里
---|components       -- Vue的公共组件,自定义的组件 全局的公共组件封装放在这里
---|env              -- 环境的变量存放 例如开发环境的配置 生产环境的配置等
---|hooks            -- hooks函数存放位置
---|layout           -- 项目布局文件
---|router           -- vue-router vue路由的配置文件,
---|store            -- 存放 vuex 为vue专门开发的状态管理器  或者,Pinia 的状态管理器 
---|style            -- 全局css less scss sass样式文件夹 
---|types            -- 全局类型定义 声明文件夹
---|utils            -- 工具库文件夹
---|views            -- 存放视图文件 vue的界面文件放这里
---|App.vue          -- 根组件
---|main.ts          -- 入口文件,因为采用了TypeScript所以是ts结尾
|-index.html         -- 项目入口文件
|-.gitignore         -- 用来配置那些文件不归git管理
|-package.json       -- 命令配置和包管理文件
|-README.md          -- 项目的说明文件,使用markdown语法进行编写
|-vue.config.ts    	 -- vite的配置文件 

2、vue-router 安装

接着我们执行以下代码安装最新 vue-router

pnpm  install vue-router

安装完成之后

src目录下的 router 文件夹 新建 index.ts 文件 ,index.ts 文件内容如下:

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
//路由创建
const constantRouterMap: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'test',
    component: () => import('@/views/testView/testView.vue'),
  },
]

const router = createRouter({
  history: createWebHistory(),
  routes: constantRouterMap,
})
export { router, constantRouterMap }

然后在 src 目录下新增permission.ts 文件

该文件的主要作用是全局的路由拦截操作文件 一般用于登录拦截

//permission.ts 文件 内容
// 路由切换之前触发
router.beforeEach((to, from, next) => {
	next()
})

// 路由切换完成后触发
router.afterEach(() => {

})

新增permission.ts 文件之后,需在src下的 main.ts中进行引入以及引入router

import { createApp } from "vue";
import "./style.css";
import "./permission";
import { router } from "@/router";

import App from "./App.vue";

createApp(App).use(router).mount("#app");

接着将 src目录下的App.vue文件进行修改 如下:




启动项目之后可以看到之前设置的 testView这几个字就是成功

3、状态管理 安装

目前vue 提供了两个状态管理 一个是vuex 一个是Pinia 选择一个即可

3.1、vuex

首先是进行安装 如下 npm 或者 yran 安装也可以

pnpm install vuex@next --save

接着在 store 目录下新建index.ts 内容如下:

import { createStore } from 'vuex'
//内容自定义 我只做了初始化
const store: any = createStore({
  modules: {
  },
  getters:{
  },
})
export default store

然后在 src 目录下的 main.ts 进行引入使用:

import { createApp } from "vue";
import "./style.css";
import "./permission";
import store from "./store";
import { router } from "@/router";
import App from "./App.vue";
import 'normalize.css/normalize.css';

createApp(App).use(router).use(store).mount("#app");

完成即可使用vuex

3.2、Pinia

首先是进行安装 如下 npm 或者 yran 安装也可以

pnpm install pinia --save

接着在 store 目录下新建index.ts 内容如下:

/**
 * 一般在容器中做这4件事
 *    1. 定义容器并导出
 *    2. 使用容器中的state
 *    3. 修改容器中的state
 *    4. 使用容器中的action
 */
import { defineStore } from "pinia";

/**
 * 1. 定义容器并导出
 * 参数一: 容器ID, 唯一, 将来 Pinia 会把所有的容器挂载到根容器
 * 参数二: 选项对象
 * 返回值: 函数, 调用的时候要空参调用, 返回容器实例
 */
export const mainStore = defineStore("main", {
  /**
   * 类似组件的 data, 用于存储全局的的状态
   * 注意:
   *    1.必须是函数, 为了在服务端渲染的时候避免交叉请求导致的数据交叉污染
   *    2.必须是箭头函数, 为了更好的 TS 类型推导
   */
  state: () => {
    return {
      count: 100,
      foo: "bar",
      age: 18,
    };
  },
  /**
   * 类似组件的 computed, 用来封装计算属性, 具有缓存特性
   */
  getters: {},
  /**
   * 类似组件的 methods, 封装业务逻辑, 修改state
   * 注意: 里面的函数不能定义成箭头函数(函数体中会用到this)
   */
  actions: {},
});

然后在 src 目录下的 main.ts 进行引入使用:

import { createApp } from "vue";
import "./style.css";
import "./permission";
import { router } from "@/router";
import { createPinia } from "pinia";
import App from "./App.vue";
import 'normalize.css/normalize.css';

createApp(App).use(createPinia()).use(router).mount("#app");

4、axios安装与封装

首先是axois 的安装

pnpm install axios --save

接着在api 文件夹下 新建 axios 文件夹

接着在 axios 文件夹 下 新建 index.tsrequest.ts

index.ts 主要是对axois 的封装 文件内容如下:

import axios, { AxiosRequestConfig, AxiosResponse, Method } from "axios";
//异常对象接口
interface ERROR_OBJ {
  [key: string | number]: string; // 字段扩展声明
}
// 定义接口
interface PendingType {
  url?: string;
  method?: Method;
  params: any;
  data: any;
  cancel: any;
}

const errorObj: ERROR_OBJ = {
  400: "参数缺失",
  // 401: '登录失效,请重新登陆!',
  // 403: '登录过期,请重新登陆!',
  404: "请求的资源不存在",
  405: "请求类型错误",
  406: "请求格式错误",
  408: "请求超时,请稍后重试!",
  500: "服务器错误,请稍后重试!",
  502: "网关错误",
  503: "服务器暂时过载或维护",
};

// 取消重复请求
const pending: Array<PendingType> = [];

/* 实例化请求配置 */
const instance = axios.create({
  // 请求时长
  timeout: 1000 * 20,
  // 请求的base地址 TODO:这块以后根据不同的模块调不同的api
  // baseURL: process.env.VUE_APP_API_URL,
  // 表示跨域请求时是否需要使用凭证
  withCredentials: false,
});
/**
 * 请求失败后的错误统一处理
 * @param {Number} status 请求失败的状态码
 */
const errorHandle = (status: any) => {
  const httpCode = status.response.status;

  //这里处理 需要token鉴权的接口
  return Promise.reject();
};

// 移除重复请求
const removePending = (config: AxiosRequestConfig) => {
  for (const key in pending) {
    const item: number = +key;
    const list: PendingType = pending[key];
    // 当前请求在数组中存在时执行函数体
    if (
      list.url === config.url &&
      list.method === config.method &&
      JSON.stringify(list.params) === JSON.stringify(config.params) &&
      JSON.stringify(list.data) === JSON.stringify(config.data)
    ) {
      // 执行取消操作
      list.cancel("操作太频繁,请稍后再试");
      // 从数组中移除记录
      pending.splice(item, 1);
    }
  }
};

request.ts 主要是对请求的封装 内容如下:

// request.ts
import { AxiosResponse } from "axios";
import axios from "./index";
export class Request {
  static request = (
    method: string,
    url: string,
    data: any
  ): Promise<AxiosResponse> => {
    return new Promise<AxiosResponse>((resolve, reject) => {
      axios({
        url,
        method,
        ...data,
      })
        .then((res: AxiosResponse) => {
          console.log("成功", res);

          resolve(res);
        })
        .catch((err) => {
          console.log("发起请求失败");
          reject(err);
        });
    });
  };
  /**
   * get方法
   * @param {string} url 路径
   * @param {object} data 参数和配置
   */
  static get = (url: string, data?: any): Promise<AxiosResponse> => {
    return this.request("get", url, data);
  };
  /**
   * post方法
   * @param {string} url 路径
   * @param {object} data 参数和配置
   */
  static post = (url: string, data?: any): Promise<AxiosResponse> => {
    return this.request("post", url, data);
  };
  /**
   * put方法
   */
  static put = (url: string, data?: any): Promise<AxiosResponse> => {
    return this.request("put", url, data);
  };
  /**
   * delete方法
   * @param {string} url 路径
   * @param {object} data 参数和配置
   */
  static delete = (url: string, data?: any): Promise<AxiosResponse> => {
    return this.request("delete", url, data);
  };
}

使用方法 例子:在api目录下新建 新建demo-api.ts 内容如下

//  api/demo-api.ts
import { Request } from "@/api/axios/request";

const demoApi = {
  test: () => Request.get(`/test/api`),
};

export default demoApi;

然后在 api 目录下新建index.ts 全部的接口通过此方式调用

//  api/index.ts
import demoApi from "./demo-api";

const api = {
  ...demoApi,
};

export default api;

5、element-plus 组件库安装与使用

5.1、安装

pnpm install element-plus @element-plus/icons-vue --save
以及
pnpm install sass sass-loader --save-dev

5.2、配置

首先安装完成之后 我们在 vite.config.ts 先进行配置 让element-plus 及 element-plus icons 能够按需自动引入 解放双手 配置如下:

import { ConfigEnv, UserConfig, defineConfig, loadEnv } from 'vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';

import path, { resolve } from 'path';
import Components from 'unplugin-vue-components/vite';
import AutoImport from 'unplugin-auto-import/vite';
import IconResolver from 'unplugin-icons/resolver';
import vueJsx from '@vitejs/plugin-vue-jsx';
import Icons from 'unplugin-icons/vite';
import vue from '@vitejs/plugin-vue';
const pathSrc = path.resolve(__dirname, 'src');
// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
	const env = loadEnv(mode, process.cwd()); // 获取.env文件里定义的环境变量
	return {
		base: env.VITE_PUBLIC_PATH, // 开发公共基础路径
		resolve: {
			//配置项目的绝对路径
			alias: {
				'@': resolve(__dirname, 'src'), // 设置 @ 指向 /src 目录
			},
		},
		server: {
			port: 8818, //端口
			host: '0.0.0.0',
			cors: true, // 默认启用并允许任何源
			//代理
			proxy: {},
		},
		plugins: [
			vue(),
			//自动导入components下的自定义组件
			Components({
				// dirs 指定组件所在位置,默认为 src/components
				// 可以让我们使用自己定义组件的时候免去 import 的麻烦
				dirs: ['src/components/', 'src/layout'],
				// 配置需要将哪些后缀类型的文件进行自动按需引入,'vue'为默认值
				extensions: ['vue', 'ts'],
				// 解析组件,这里以 Element Plus 为例
				resolvers: [
					ElementPlusResolver({
						importStyle: 'sass', // 非官方,必要
					}),
					IconResolver({ enabledCollections: ['ep'] }),
				],
				// 遍历子目录
				deep: true,
				dts: path.resolve(pathSrc, 'types', 'components.d.ts'), // 指定自动导入组件TS类型声明文件路径
			}),
			//自动导入组件
			AutoImport({
				imports: ['vue', 'vuex', 'vue-router'],
				dts: path.resolve(pathSrc, 'types', 'auto-imports.d.ts'), // 指定自动导入函数TS类型声明文件路径
				eslintrc: {
					enabled: true,
					filepath: path.resolve(
						pathSrc,
						'types',
						'.eslintrc-auto-import.json'
					),
					globalsPropValue: true,
				},
				resolvers: [ElementPlusResolver(), IconResolver({ prefix: 'Icon' })],
			}),
			//自动导入图标
			Icons({ scale: 1, defaultClass: 'inline-block', autoInstall: true }),
			//vueJsx
			vueJsx({}),
		],
	};
});


5.3 引入及项目配置

当做完前面步骤之后需要进行引入及在项目中配置

需要在 src 目录下 main.ts引入 el-message 样式 否则el-message 样式会有失效问题

import { createApp } from 'vue';
import './style.css';
import './permission';
import { router } from '@/router';
import { createPinia } from 'pinia';
import App from './App.vue';
import 'normalize.css/normalize.css';
// 引入 element样式
import 'element-plus/theme-chalk/el-message.css'
import 'element-plus/theme-chalk/el-message-box.css'

createApp(App).use(createPinia()).use(router).mount('#app');

接着在 src 目录下 的App.vue进行全局配置





最后 在 types 目录下新建 element-plus.d.ts

declare module 'element-plus/dist/locale/zh-cn';

declare module 'element-plus/dist/locale/zh-cn.mjs';

6、eslint、Prettier 安装与配置

6.1、安装ESLint、Prettier相关包

pnpm install eslint eslint-plugin-vue eslint-config-prettier prettier eslint-plugin-import eslint-plugin-prettier eslint-config-airbnb-base -save-dev
  1. eslint: ESLint的核心代码库
  2. prettier: Prettier的格式化代码的核心代码库
  3. eslint-config-airbnb-base: airbnb的代码规范(依赖plugin-import)
  4. eslint-config-prettier: eslint结合prettier的格式化
  5. eslint-plugin-vue: eslint在Vue里的代码规范
  6. eslint-plugin-import: 项目里面支持eslint

6.2、配置scripts脚本

在 根目录下的 package.json 中增加配置

"scripts": {
	"lint:create": "eslint --init",
}

执行ESLint配置的交互式命令

npm run lint:create

配置ESLint过程如下

//执行npm run lint:create 
> npm run lint:create 
//会出现如下代码 选择第二个就好
You can also run this command directly using 'npm init @eslint/config'.
? How would you like to use ESLint? ... 
  To check syntax only
> To check syntax and find problems
  To check syntax, find problems, and enforce code style
//接着依次选择如下
You can also run this command directly using 'npm init @eslint/config'.
√ 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
√ What format do you want your config file to be in? · JavaScript
The config that you've selected requires the following dependencies:

@typescript-eslint/eslint-plugin@latest eslint-plugin-vue@latest @typescript-eslint/parser@latest
√ Would you like to install them now? · No / Yes
√ Which package manager do you want to use? · pnpm

此时项目根目录自动生成了.eslintrc.cjs文件

接着对.eslintrc.cjs文件 进行重写 代码如下

module.exports = {
  // 环境:
	env: {
		// 浏览器
		browser: true,
		// 最新es语法
		es2021: true,
		// node环境
		node: true,
	},
  // 扩展的eslint规范语法,可以被继承的规则
	// 字符串数组:每个配置继承它前面的配置
	// 分别是:
	// eslint-plugin-vue提供的
	// eslint-config-airbnb-base提供的
	// eslint-config-prettier提供的
	// 前缀 eslint-config-, 可省略
	extends: ['plugin:vue/vue3-strongly-recommended', 'airbnb-base', 'prettier'],
	// eslint 会对我们的代码进行检验
	// parser的作用是将我们写的代码转换为ESTree(AST)
	// ESLint会对ESTree进行校验
	parser: 'vue-eslint-parser',
	// 解析器的配置项
	parserOptions: {
		// es的版本号,或者年份都可以
		ecmaVersion: 'latest',
		parser: '@typescript-eslint/parser',
		// 源码类型 默认是script,es模块用module
		sourceType: 'module',
		// 额外的语言类型
		ecmaFeatures: {
			tsx: true,
			jsx: true,
		},
	},
  // 全局自定义的宏,这样在源文件中使用全局变量就不会报错或者警告
	globals: {
		defineProps: 'readonly',
		defineEmits: 'readonly',
		defineExpose: 'readonly',
		withDefault: 'readonly',
	},
  // 插件
	// 前缀 eslint-plugin-, 可省略
	// vue官方提供了一个ESLint插件 eslint-plugin-vue,它提供了parser和rules
	// parser为 vue-eslint-parser,放在上面的parser字段,rules放在extends字段里,选择合适的规则
	plugins: ['vue', '@typescript-eslint', 'unused-imports'],
  settings: {
		// 设置项目内的别名
		'import/resolver': {
			alias: {
				map: [['@', './src'],['/assets', './src/assets']],
        extensions: ['.ts', '.js', 'tsx', 'jsx'] // 解决:Unable to resolve path to module
			},
      // "node": {
      //   "extensions": [".js", ".jsx", ".ts", ".tsx"]
      // }
		},
		// 允许的扩展名
		'import/extensions': ['.js', '.jsx', '.ts', '.tsx', '.mjs'],
	},
  overrides: [
    {
      env: {
        node: true,
      },
      files: [".eslintrc.{js,cjs}"],
      parserOptions: {
        sourceType: "script",
      },
    },
  ],
  rules: {
    'no-console': 0,   // 项目中可以使用console.log()
		'vue/valid-template-root': 0,
    'import/no-extraneous-dependencies': 0,   // 解决vite.config.ts的引入报错
		'vue/multi-word-component-names': 0,
		'vue/attribute-hyphenation': 0,
		'vue/v-on-event-hyphenation': 0,
		// 'eslint-plugin-unused-vars': 0,
		"no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off",
		"unused-imports/no-unused-imports": "error",
		"unused-imports/no-unused-vars": [
			"warn",
			{ "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" }
		],
    "func-names": 0,    // 关闭匿名函数的校验
    "import/extensions": 0,   // import时省略后缀名
    "vue/no-mutating-props": 0,  // 关闭子组件改变props时的报错  baseForm
    'no-undef': 0,  // 解决按需导入ElMessage  未定义的问题
    //  already declared in the upper scope
    "no-shadow": 0,
	"spaced-comment":0,
	"import/newline-after-import": 0, 
	"import/no-unresolved":0,
	"import/no-named-as-default":0,
	"import/no-named-as-default-member":0,
	"import/no-relative-packages":0,
	"import/no-cycle":0,
	"import/no-self-import":0,
	"import/order":0,
	"import/no-duplicates":0
  },
};

接着安装 eslint支持插件

pnpm install vite-plugin-eslint --save-dev

在根目录的 vite.config.ts 新增

import eslintPlugin from "vite-plugin-eslint";
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
       ....,
      plugins: [
         ....,
           eslintPlugin(),                
      ]  
 })

完整vite.config.ts 如下

import { ConfigEnv, UserConfig, defineConfig, loadEnv } from "vite";
import path, { resolve } from "path";
import Components from "unplugin-vue-components/vite";
import AutoImport from "unplugin-auto-import/vite";
//import IconResolver from "unplugin-icons/resolver";
import eslintPlugin from "vite-plugin-eslint";
import vueJsx from "@vitejs/plugin-vue-jsx";
import Icons from "unplugin-icons/vite";
import vue from "@vitejs/plugin-vue";
const pathSrc = path.resolve(__dirname, "src");
// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
  const env = loadEnv(mode, process.cwd()); // 获取.env文件里定义的环境变量
  return {
    base: env.VITE_PUBLIC_PATH, // 开发公共基础路径
    resolve: {
      //配置项目的绝对路径
      alias: {
        "@": resolve(__dirname, "src"), // 设置 @ 指向 /src 目录
      },
    },
    server: {
      port: 8818, //端口
      host: "0.0.0.0",
      cors: true, // 默认启用并允许任何源
      //代理
      proxy: {},
    },
    plugins: [
      vue(),
      //自动导入components下的自定义组件
      Components({
        // dirs 指定组件所在位置,默认为 src/components
        // 可以让我们使用自己定义组件的时候免去 import 的麻烦
        dirs: ["src/components/", "src/layout"],
        // 配置需要将哪些后缀类型的文件进行自动按需引入,'vue'为默认值
        extensions: ["vue", "ts"],
        // 解析组件,这里以 Element Plus 为例
        resolvers: [],
        // 遍历子目录
        deep: true,
        dts: path.resolve(pathSrc, "types", "components.d.ts"), // 指定自动导入组件TS类型声明文件路径
      }),
      //自动导入组件
      AutoImport({
        imports: ["vue", "vuex", "vue-router"],
        dts: path.resolve(pathSrc, "types", "auto-imports.d.ts"), // 指定自动导入函数TS类型声明文件路径
        eslintrc: {
          enabled: true,
          filepath: path.resolve(
            pathSrc,
            "types",
            ".eslintrc-auto-import.json"
          ),
          globalsPropValue: true,
        },
      }),
      //自动导入图标
      Icons({ scale: 1, defaultClass: "inline-block", autoInstall: true }),
      //vueJsx
      vueJsx({}),
      //eslint
      eslintPlugin(),
    ],
  };
});

eslint 配置完成 接下来你可以添加script脚本命令 然后选择一个vue文件写一端错误代码 然后运行脚本指令 如果有报错则eslint配置成功

"lint": "eslint \"src/**/*.{js,vue,ts}\" --fix"

运行命令

pnpm run lint

6.3、ESLint和Prettier结合使用

接着需要建立3个文件

.eslintrcignore 用于排除一些不需要eslint校验的文件

.prettierrc.cjs 设置保存自动格式化规则

.prettierignore 用于排除一些不需要prettier校验的文件

.eslintrcignore 内容如下:

*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.history
/bin
.eslintrc.js
prettier.config.js
/src/mock/*
vite.config.ts
public/
assets/
build/
vite/
*.html

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

.DS_Store
dist-ssr
*.local

/cypress/videos/
/cypress/screenshots/

# Editor directories and files
.vscode
!.vscode/extensions.json
.idea
*.suo
*.njsproj
*.sln
*.sw?

components.d.ts

.prettierrc.cjs 内容如下:

module.exports = {
	// 一行最多多少字符
	printWidth: 80,
	// 使用2个空格缩进
	tabWidth: 2,
	// 使用tab缩进,不使用空格
	useTabs: true,
	// 行尾需要分号
	semi: true,
	// 使用单引号
	singleQuote: true,
	// 对象的key仅在必要时使用引号
	quoteProps: "as-needed",
	// jsx不使用单引号,而使用双引号
	jsxSingleQuote: false,
	// 尾随逗号
	trailingComma: "es5",
	// 大括号内的收尾需要空格
	bracketSpacing: true,
	// 箭头函数,只有一个参数的时候,也需要括号
	arrowParens: "always",
	// 每个文件格式化的范围是文件的全部内容
	rangeStart: 0,
	rangeEnd: Infinity,
	// 不需要写文件开头的@prettier
	requirePragma: false,
	// 不需要自动在文件开头插入@prettier
	insertPragma: false,
	// 使用默认的折行标准
	proseWrap: "always",
	// 根据显示样式决定html要不要折行
	htmlWhitespaceSensitivity: "css",
	// 换行符使用lf
	endOfLine: "lf",
}

.prettierignore 内容如下:

*
!src/**/
!**/*.js
!**/*.jsx
!**/*.css
!**/*.scss
!**/*.html
!**/*.vue
!**/*.md
!**/*.ts
!**/*.tsx

# some souces directories
src/assets
/dist/*
.local
.husky
.history
.output.js
/node_modules/**
src/.DS_Store
**/*.svg
**/*.sh
/public/*
components.d.ts
#
CHANGELOG.md
vue.config.js
babel.config.js
commitlint.config.js
vite.config.js
.eslintrc.js

5.4 项目启动依赖安装

pnpm install typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-import-resolver-alias @types/eslint @types/node -save-dev

@typescript-eslint/parser: ESLint的解析器,用于解析typescript,从而检查和规范typescript代码
@typescript-eslint/eslint-plugin: 这是一个ESLint插件,包含了各类定义好的检测Typescript代码的规范
eslint-import-resolver-alias: import的时候使用@等别名

最后对 根目录下的 tsconfig.ts 文件进行重写

module.exports = {
  // 环境:
	env: {
		// 浏览器
		browser: true,
		// 最新es语法
		es2021: true,
		// node环境
		node: true,
	},
  // 扩展的eslint规范语法,可以被继承的规则
	// 字符串数组:每个配置继承它前面的配置
	// 分别是:
	// eslint-plugin-vue提供的
	// eslint-config-airbnb-base提供的
	// eslint-config-prettier提供的
	// 前缀 eslint-config-, 可省略
	extends: ['plugin:vue/vue3-strongly-recommended', 'airbnb-base', 'prettier','./.eslintrc-auto-import.json'],
	// eslint 会对我们的代码进行检验
	// parser的作用是将我们写的代码转换为ESTree(AST)
	// ESLint会对ESTree进行校验
	parser: 'vue-eslint-parser',
	// 解析器的配置项
	parserOptions: {
		// es的版本号,或者年份都可以
		ecmaVersion: 'latest',
		parser: '@typescript-eslint/parser',
		// 源码类型 默认是script,es模块用module
		sourceType: 'module',
		// 额外的语言类型
		ecmaFeatures: {
			tsx: true,
			jsx: true,
		},
	},
  // 全局自定义的宏,这样在源文件中使用全局变量就不会报错或者警告
	globals: {
		defineProps: 'readonly',
		defineEmits: 'readonly',
		defineExpose: 'readonly',
		withDefault: 'readonly',
	},
  // 插件
	// 前缀 eslint-plugin-, 可省略
	// vue官方提供了一个ESLint插件 eslint-plugin-vue,它提供了parser和rules
	// parser为 vue-eslint-parser,放在上面的parser字段,rules放在extends字段里,选择合适的规则
	plugins: ['vue', '@typescript-eslint', 'unused-imports'],
  settings: {
		// 设置项目内的别名
		'import/resolver': {
			alias: {
				map: [['@', './src'],['/assets', './src/assets']],
        extensions: ['.ts', '.js', 'tsx', 'jsx'] // 解决:Unable to resolve path to module
			},
      // "node": {
      //   "extensions": [".js", ".jsx", ".ts", ".tsx"]
      // }
		},
		// 允许的扩展名
		'import/extensions': ['.js', '.jsx', '.ts', '.tsx', '.mjs'],
	},
  overrides: [
    {
      env: {
        node: true,
      },
      files: [".eslintrc.{js,cjs}"],
      parserOptions: {
        sourceType: "script",
      },
    },
  ],
  rules: {
    'no-console': 0,   // 项目中可以使用console.log()
		'vue/valid-template-root': 0,
    'import/no-extraneous-dependencies': 0,   // 解决vite.config.ts的引入报错
		'vue/multi-word-component-names': 0,
		'vue/attribute-hyphenation': 0,
		'vue/v-on-event-hyphenation': 0,
		// 'eslint-plugin-unused-vars': 0,
		"no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off",
		"unused-imports/no-unused-imports": "error",
		"unused-imports/no-unused-vars": [
			"warn",
			{ "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" }
		],
    "func-names": 0,    // 关闭匿名函数的校验
    "import/extensions": 0,   // import时省略后缀名
    "vue/no-mutating-props": 0,  // 关闭子组件改变props时的报错  baseForm
    'no-undef': 0,  // 解决按需导入ElMessage  未定义的问题
    //  already declared in the upper scope
    "no-shadow": 0,
  },
};

你可能感兴趣的:(vue3+vite项目实战,vue.js,前端)