一、前言
在开发工具这部分开始,介绍一些开发工具的使用过的后总结的一些经验吧,仅供大家参考,正确使用以官方文档为准,如果发现有错误或者不理解的地方,可以给我留言,我会将反馈加以改正,以此完成更好的文章,这次向大家分享一下Axios的使用经验吧!
二、简单理解
说明: Axios是一个运行在浏览器或nodeJS环境的js库,但是这个库是支持promise的,它可以向后台请求数据,跟普通的ajax请求相比,它可以在请求的过程中做更多可控的工作,以此管理发送的请求和请求回来的数据。
三、关于请求
说明: 在一个项目之中,可以新建一个service的文件夹用来管理项目中的所有请求,当然这个文件夹名也可以使server、http等,这样建文件夹的好处在于语义化(也可以说是开发者自己的规定吧),方便以后的开发者能很容易知道当前文件夹具体放置的是什么内容
注意: 因为Axios是用ts实现的,并且ts语法拥有良好的提示,所以在service文件夹中新建ts文件来管理请求,如果相对axios的使用做一些更改,可以在service文件夹下新建一个service.config.ts文件来管理,配置这个文件需要了解一个环境变量的问题
四、环境变量
说明: 这个环境变量是整个Vue项目运行起来的环境变量
定义: 关于环境变量的定义可以在根目录下面放置一下文件来指定环境变量,在使用的时候所有key值均大写,并且所有的字符串不带引号
相关文件的作用:
.env:定义的内容在任何模式下都会加载(开发环境和生产环境都会加载).env.local:在本地运行时,定义的内容在任何模式下都会加载.env.development:定义的内容在开发模式下面加载.env.development.local:在本地运行时,定义的内容在开发模式下面加载.env.production:定义的内容在生产模式下面加载.env.production.local:在本地运行时,定义的内容在生产模式下面加载
举例: 在项目开发的时候和项目上线的时候服务器的地址会不一样,那就可以通过环境变量来解决项目在两个不同阶段服务器地址不同的问题,此时就可以在开发环境和生产环境提前写好项目所运行的服务器地址,这样就完成了环境变化
// .env.production(生产环境)
// 这样别人就看不见ip地址,只能看到域名了
VUE_APP_BASE_URL = http://api.cc0820.top0:7001
// .env.development(开发环境)
// 配置请求地址不能使用BASE_URL,需要使用VUE_APP_自定义
VUE_APP_BASE_URL = http://192.168.121.66:7001
//配置端口号,如果端口号被占用会往上加一个
VUE_APP_PORT = 9000
// service.config.ts(上面所定义的环境变量就可以在配置文件
// 中来使用了)
// 在配置文件中可以通过process.env.环境变量名
// 来获取到定义到的环境变量的值
process.env.VUE_APP_BASE_URL
注意: 在环境变量文件中,只能使用三种类型的key: BASE_URL,NODE_ENV,VUE_APP_开头的变量才能够被获取到,并且不可以随意使用标点符号,如果添加可能会出现意料之外的问题
优点: 将需要配置的配置项都将其放置在.env文件里面集中配置处理,通过process.env.环境变量名获取配置的环境变量
五、Axios的使用
// 在上述的配置文件service.config.ts中书写一下内容,
// 以此完成请求的axios的基本配置
import axios from "axios"
// 使用create创建一个axios的子函数
const service = axios.create({
// 表示所有请求中不变化的那部分地址称为基础地址
baseURL:process.env.VUE_APP_BASE_URL
// 服务器超过多少秒没有返回数据就会自动断开
timeout:5000
})
// 最后将这个子函数导出
export default service
// 发送get请求
import service from "./service.config"
export const getUserName = ( username ) =>
service.get("/api/v1/users/exists_user_unique_fields", {
// 携带的参数使用params表示
params: { username }
})
// 发送post请求
import service from "./service.config"
// post请求不需要params来传递
export const getUserName = ( username ) =>
service.get("/api/v1/users/exists_user_unique_fields", username)
// 使用这个函数之前需要先导入这个函数
import { getUserName } from "./index.ts"
// 在方法中定义一个异步函数用来拿到请求返回的数据
async getChange() {
// 成功时用同步的方式将返回值接住,失败的时候调用catch方法
const result = await getUserName(需要传递的参数).catch((err) => {
console.log(err)
})
}
六、请求拦截和响应拦截
说明: 请求拦截器和响应拦截器的使用需要借助上面创建的子函数service,拦截器都存在两个函数参数,分别为成功和失败的时候所执行的函数
请求拦截:如果向服务器询问一个问题,在问题到达服务器中间存在很多环节,在某个环节上,并没有将问题如实传递给服务器或者在问题中添加了一些自定义的内容,这个环节则称为请求拦截
请求拦截器:service.interceptors.request.use()
// 函数参数为请求携带的数据配置
service.interceptors.request.use(function(config){
// 查看请求的内容
console.log(config)
// 将请求转发出去,如果不转发请求,服务器不会收到
// 这个请求,当然也不会响应数据,从而完成了拦截的效果
return config
})
响应拦截器:service.interceptors.response.use()
// 函数参数为服务器相应的数据
service.interceptors.response.use(function(response){
// 查看请求响应的数据
console.log(response)
// 将响应的数据转发出去,不转发getChange函数会
// 拿不到响应回来的数据
return response
})
七、请求失败的处理
自己决定成功或失败的请求
service.interceptors.response.use(function(response){
// 如果我想要上面书写的getChange函数不是在then里面
// (result)拿到数据,而是在catch中拿到数据,
// 可以使用promise的静态方法reject去完成,返回一个
// 响应失败的函数,此时在getChange函数哪里就会走失
// 败catch的方法这样我就可以自己觉得正确的响应走then,
// 不正确的响应走catch
return Promise.reject(response)
})
请求失败的集中处理
// 将所有响应失败的请求捕获到
service.interceptors.response.use(function(response){
// 在这个地方使用catch,避免了在getChange函数中使用,
// 做到将响应成功和失败进行分隔开,在promise里面,
// 如果存在响应失败,必须写catch函数,否则会报错在这
// 里还需要通过状态码进行判断是否这个请求是失败的,
// 状态码一般存放在data里面的code里面,这里我成功的
// 状态码为200
if(response.data.code === 200) {
return response.data
}
// 那么现在的catch的这个地方就变成了处理所有响应失
// 败的地方,可以写一个函数来处理
return Promise.reject(response).catch(errorHeadle)
})
// 这里就可以写出如果出现了什么错误该如何解决
// (一般给弹框来作为提示)
const errorHeadle = (error) => {
// 使用element-ui里面的Notification弹框
Notification({
type: 'error',
tittle: '错误',
message: error.data.msg
})
}
八、Tooken的存储
定义: 它是一个由服务器生成的一个加密的字符串,以此作为客户端请求的一个令牌,当用户第一次使用账号密码登陆后,服务器便会生成一个Tooken和Tooken的失效时间返回给客户端,如果成功登陆,以后客户端只需要在有限时间带上这个Tooken来请求数据就可以,不用再次填写密码和用户名。
存储:
// storejs是对storage进行一个封装的js库,
// get为获取 / set为存储
import store from "storejs";
// 请求拦截
service.interceptors.request.use(function (config) {
// 2.当请求成功后便会发生路由跳转,此时边将存储
// 在本地的Tooken放置在请求头部的Authorization
// 配置中
const auth = store.get("auth");
if (auth) {
config.headers.set("Authorization", `Bearer ${auth.accessToken}`);
}
return config;
});
// 响应拦截
// 1.因为只有用户名和密码在服务器端验证通过,才会
// 返回响应的数据以及Tooken,也就是说在响应成功
// 函数里面是可以最先可以拿到Tooken的值的,此时,
// 将这个token存储下来
service.interceptors.response.use(function (response) {
// 根据给定的成功的code值断定该请求是否成功
if (response.data.code === 0) {
if (
// 判断当前响应是否是登陆页面的响应并且请求的方式是指定的
response.config.url === "/api/v1/users/login" &&
response.config.method === "post"
) {
// 如果是,那就将里面携带的Tooken存储起来
store.set("auth", response.data.data);
}
return response.data;
}
return Promise.reject(response).catch(errorHandler);
});
export default service;