vue3+ts
vue3+ts后台管理
1.项目搭建配置文件
在搭建项目的时候会统一规范,比如统一编辑器中的tab键的空格数目,还有对于代码格式的美化,通过.prettierrc文件设置
1 | { |
- useTabs:使用tab缩进还是空格缩进,选择false;
- tabWidth:tab是空格的情况下,是几个空格,选择2个;
- printWidth:当行字符的长度,推荐80,也有人喜欢100或者120;
- singleQuote:使用单引号还是双引号,选择true,使用单引号;
- trailingComma:在多行输入的尾逗号是否添加,设置为
none; - semi:语句末尾是否要加分号,默认值true,选择false表示不加;
通过.editorconfig文件配置编辑器
1 | # http://editorconfig.org |
此时通过保存就可以自动格式化代码,如果想要更加简单,省去手动保存的步骤,就需要对webpack进行配置
2.vue.config.js配置
vue.config.js默认是通过module.exports进行导出的,因为这些文件都是在node环境下运行的,node是支持common.js的。
配置方式有以下几种
1 | module.exports = { |
3.初始化vue-router
1 | //首先从vue-router中引入创建路由所需要的文件 |
因为是使用ts,所以需要对routes进行类型限制,可以通过interface对routes进行手动设置
但是因为routes对象是作为createRouter函数的一个参数,所以在createRouter中已经对其进行了类型限制,通过ctrl+左键点进去可以找到routes的类型为routes: RouteRecordRaw[];
所以需要对routes进行类型设置
最后需要在main.ts文件中对导出的router进行注册
app.use(router)
4.初始化vuex
1 | //1.首先导入vuex创建函数 |
最后需要在main.ts文件中对导出的vuex进行注册app.use(store)
5.按需引入element-plus
需要下载插件npm install babel-plugin-import -D
不太需要按需引入
6.环境配置
如果遇到需要切换环境的情况,比如生产、开发、测试环境,可以通过process.env.NODE_ENV这个语句进行判断,webpack在打包的时候会将当时的环境通过DefinePlugin插件注入到这个语句中,process.env.NODE_ENV在开发环境的值为development,在生产环境的值为production,在测试环境的值为test
另外,在vue-cli脚手架的环境下,可以通过在根目录上创建.env.development、.env.production、.env.test三个文件,文件内部中文件命名需要按照以以下格式VUE_APP_随意内容,然后通过process.env.VUE_APP_随意内容取到
7.ts封装axios
ts相关
Promise本身是可以有类型的,在ts中
1 | new Promise<string>((resolve, reject) => { |
如果通过泛型传入其他类型的,例如

提示中就指出传入的参数需要是string或者promiselike<string>,此时的泛型所指定的.then()中的res参数类型也是string类型,所以在之后的回调函数中就可以看到res.length的属性提示
在axios的声明文件中看到这样的代码
1 | export interface AxiosInstance extends Axios { |
上面代码的第二行表示,(config: AxiosRequestConfig)是一个函数,他的类型是AxiosPromise类型,这里面比较特殊的就是这个函数并没有定义函数名,只要是参数类型符合规则的,就是相应的类型
1 | export interface AxiosInterceptorManager<V> { |
上述代码中,接口AxiosTnterceptorManager中传入了一个泛型V。这个接口中定义了一个名为use的函数,use函数也传入了一个泛型T这个泛型类型是V,同时use函数中也有也有两个指定名字的函数作为参数onFulfilled与onRejected
正式封装axios
这里为了封装axios创建了一个
service文件夹,该文件夹的入口文件为index.ts1
2
3
4
5
6
7
8import XRequest from './request'
import { BASE_URL, TIME_OUT } from './request/config'
const xRequest = new XRequest({
baseURL: BASE_URL,
timeout: TIME_OUT
})
export default xRequest该文件导出了已经封装好了的
xRequest(随意命名的,yylx最后字母命名的)之后在
request文件夹中编写XRequest类,用来封装axios为了解决当有多个不同
base_url需要进行网络请求的问题,在XRequest类中创建了instance用于保存axios实例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
class XRequest {
// 创建一个axios实例
instance: AxiosInstance
constructor(config: AxiosRequestConfig) {
// 在创建xRequest实例的时候,传入config,之后赋值给该实例的instacne
// 这样就可以保证每个xRequest实例保持独立,当BASE_URL不同的时候,每个xRequest实例发送请求时互不干扰
this.instance = axios.create(config)
}
request(config: AxiosRequestConfig): void {
// 这里的instance就相当于一个axios实例,他有axios实例可以拥有的所有方法
this.instance.request(config).then((res) => {
console.log(res)
})
}
}
export default XRequest这里需要注意的是在构造函数
constructor中的参数config的类型如何确定:因为config要作为axios.create()的参数传递进去,所以要符合这个函数的参数类型规定,这个类型在axios的ts声明文件中有定义,可以直接拿过来用在axios实例创建好之后,就可以封装request请求了,通过
this.instance.request(config).then(res=>{}),之后通过xRequest.request(config)就可以实现通过封装的axios发送网络请求下面就是重头戏添加拦截器
封装好的
XRequest类希望可以传入interceptors拦截器,同时也可以传入AxiosRequestConfig类型的属性,所以此时传入的config就不能是AxiosRequestConfig类型了,需要自定义一个接口XRequestConfig类型去包括AxiosRequestConfig和interceptors属性1
2
3interface XRequestConfig extends AxiosRequestConfig {
interceptors?: XRequestInterceptors
}然后需要确定拦截器中有哪些属性
1
2
3
4
5
6
7
8interface XRequestInterceptors {
// 这里面的config类型可以从this.instance.interceptors.request.use()中查看
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (error: any) => any
// 这里的congfig类型查看地方同上
responseInterceptor?: (config: AxiosResponse) => AxiosResponse
responseInterceptorCatch?: (error: any) => any
}
接口类型出处:当调用
use()方法的时候,其参数类型就被规定了,其中传入的泛型V,就是config的类型完整的封装类XRequest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26class XRequest {
// 创建一个axios实例
instance: AxiosInstance
interceptors?: XRequestInterceptors
// 自定义的接口类型,除了AxiosRequestConfig,还有额外的可选拦截器属性
constructor(config: XRequestConfig) {
// 在创建xRequest实例的时候,传入config,之后赋值给该实例的instacne
// 这样就可以保证每个xRequest实例保持独立,当BASE_URL不同的时候,每个xRequest实例发送请求时互不干扰
this.instance = axios.create(config)
this.interceptors = config.interceptors
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptorCatch
)
this.instance.interceptors.response.use(
this.interceptors?.responseInterceptor,
this.interceptors?.responseInterceptorCatch
)
}
request(config: AxiosRequestConfig): void {
// 这里的instance就相当于一个axios实例,他有axios实例可以拥有的所有方法
this.instance.request(config).then((res) => {
console.log(res)
})
}
}这时候就可以在
service/index.ts中在实例化的时候传入拦截器了为每个请求单独添加自己的拦截器
因为请求需要添加自己的拦截器,所以此时请求的参数
config的类型就不能是AxiosRequestConfig类型了,修改成XRequestConfig类型1
2
3
4export interface XRequestConfig extends AxiosRequestConfig {
interceptors?: XRequestInterceptors
showLoading?: boolean
}因为已经将请求
request进行了封装,所以可以自己手动实现一个拦截器:
因为拦截器本身就相当于在发送请求前去调用一个函数,处理相关逻辑,所以要实现每个请求单独拦截的话,就可以在发送请求前,手动去调用传进来这个函数,也就是
该请求需要单独拦截所要实现的逻辑代码,官方的拦截器是自动的调用,如果要自己用就需要手动去调






