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 文件文件内容如下:
<template>
<div>testView</div>
</template>
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文件进行修改 如下:
<template>
<router-view></router-view>
</template>
<script setup lang="ts"></script>
启动项目之后可以看到之前设置的 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.ts 与 request.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进行全局配置
<template>
<el-config-provider :locale="locale" name="el" :message="config">
<router-view></router-view>
</el-config-provider>
</template>
<script setup lang="ts">
import zhCn from 'element-plus/dist/locale/zh-cn';
const locale = zhCn;
// 然后将element-ui中pagination选项改掉
zhCn.el.pagination = {
pagesize: '条/页',
total: `共 {total} 条`,
goto: '前往第',
pageClassifier: '页',
};
const config = reactive({
max: 4,
});
</script>
最后 在 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
- eslint: ESLint的核心代码库
- prettier: Prettier的格式化代码的核心代码库
- eslint-config-airbnb-base: airbnb的代码规范(依赖plugin-import)
- eslint-config-prettier: eslint结合prettier的格式化
- eslint-plugin-vue: eslint在Vue里的代码规范
- 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的时候使用@等别名文章来源:https://uudwc.com/A/GdEEe
最后对 根目录下的 tsconfig.ts 文件进行重写文章来源地址https://uudwc.com/A/GdEEe
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,
},
};