0%

Vue3中axios的基本使用与封装

本文主要介绍axios的基本使用,包括如何引入、常用API、拦截器的用法,以及Vue3中对axios的封装

axios的基本使用

安装axios

使用npm安装axios到项目中

1
npm install axios

局部引入axios

如果只想在单个组件中使用axios,只需要在这个文件中引入axios

1
2
3
4
5
6
7
8
9
10
import axios from 'axios'

onMounted(() => {
getData()
})

const getData = async ()=>{
const response = await axios.get('/hangzhou.json')
console.log(response.data.features);
}


其中,axios.get('/url')将会返回一个 Promise 对象,Promise对象代表一个异步操作的最终完成或者失败,以及其返回的值。一个 Promise 对象有三种状态: 1. Pending 进行中:初始状态,表示操作尚未完成,仍在进行中; 2. Fulfilled 已成功:表示异步操作已成功完成,并且有一个返回值,包括datastatusheaders等属性; 3. Rejected 已失败:表示异步操作失败,并提供一个失败的原因。

  • Promise的内部原理: 在手动创建一个 Promise 实例时,可以传入执行器函数executor(),该函数接收两个参数:resolvereject,这两个参数都是函数,用于将 Promise对象 从 Pending 状态转变为 Fulfilled 或 Rejected 状态
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const promise = new Promise((resolve, reject) => {
    // 异步操作,比如发送网络请求、读取文件等
    // 当操作成功时,调用 resolve,并传递结果
    // 当操作失败时,调用 reject,并传递失败的原因
    if (/* 操作成功 */) {
    resolve('成功的结果');
    } else {
    reject('失败的原因');
    }
    });

我们可以通过.then()方法来处理异步操作成功时的情况,以及通过.catch()方法来处理异步操作失败时的情况。

1
2
3
4
5
6
7
8
9
promise
.then((result) => {
// 处理操作成功的情况
console.log('成功:', result);
})
.catch((error) => {
// 处理操作失败的情况
console.error('失败:', error);
});

Promise 提供了链式调用的能力,可以通过比如.then().then()链式地处理异步操作,这样有助于更清晰地组织和处理多个异步操作。

1
2
3
4
5
6
7
8
9
10
11
promise
.then((result) => {
// 第一个异步操作成功后的处理
return newPromise(result);
})
.then((newResult) => {
// 第二个异步操作成功后的处理
})
.catch((error) => {
// 处理任意一个异步操作失败的情况
});

由于Promise 是一种处理异步操作的方式,需要一定的时间等待异步操作完成,因此使用await等待异步操作完成,并获取其结果,以便在后续代码中进行进一步的处理或者基于结果执行其他操作。不等待异步操作完成,直接进行后续代码可能会导致数据未准备好或者操作未完成就进行处理,造成不可预测的结果或错误。

在使用await关键字之前,函数需要被标记为async,这样才能在函数内部使用await来等待 Promise 完成。

全局引入axios

如果想要全局引入axios,我们可以借助 Vue3 新提供的provideinject方法来实现

  1. 在入口文件main.js中使用provide方法注入axios
    1
    2
    3
    4
    5
    6
    7
    import { createApp } from 'vue'
    import App from './App.vue'
    import axios from 'axios'

    const app = createApp(App)
    app.provide('$axios',axios)
    app.mount('#app')
  2. 在需要使用axios的组件使用inject方法调用即可
    1
    2
    3
    const axios = inject('$axios')
    const response = await axios.get('/hangzhou.json')
    console.log(response.data.features)

调用示例

GET请求

简单调用

1
2
3
4
5
6
7
axios.get('/api/data', {id : 123})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
完整调用
1
2
3
4
5
6
7
8
9
10
11
12
13
axios({
method: 'get',
url: '/api/data',
params: {
id: 123
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
#### POST请求 简单调用
1
2
3
4
5
6
7
axios.post('/api/data', { name: 'John', age: 30 })
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
完整调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
axios({
method: 'post',
url: '/api/data',
data: {
name: 'John',
age: 30
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

axios的拦截器

拦截器是axios提供的一种强大的机制,用于在请求或响应被处理之前对其进行拦截和转换。在axios的全局配置中,可以配置请求拦截器和响应拦截器。请求拦截器可以用于在发送请求之前对请求进行修改、添加请求头等操作;而响应拦截器可以用于在收到响应后对响应进行修改、数据转换、错误处理等操作。

请求拦截器的使用方法:

1
2
3
4
5
6
7
8
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么,比如添加请求头等操作
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});

响应拦截器的使用方法:

1
2
3
4
5
6
7
8
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});

移除拦截器:将请求拦截器赋给变量,在不需要使用的时候,调用request.eject(变量)方法

1
2
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);

Vue3中对axios的封装

在我们实际开发项目时,一个项目往往会涉及到很多接口,如果我们按照上面的方法去调用网络请求的话,每次都要去写一遍上面的方法,这将是一件非常恐怖的事情。后期如果需求有变更,比如url地址变了,那我们的工作量就是成倍的增加了。所以,在实际的开发中,我们都会将axios进行封装。我在实际的开发中会将网络相关的业务独立放到一个文件夹中,创建两个文件夹utilsapiutils文件夹存放 request.js 文件用于封装 axios 请求、api文件夹存放 user.js 文件用于封装关于用户所有的 API 请求。详细步骤如下:

  1. 在 request.js 中引入 axios,并封装 axios 请求

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    import axios from 'axios'

    const service = axios.create({
    baseURL: '/api' //定义URL公共前缀,定义为`/api`是为了解决跨域问题
    timeout: 5000 //定义超时时间
    })

    // 请求拦截器
    service.interceptors.request.use(
    config => {
    // 添加请求头等前置处理
    config.headers['Authorization'] = 'Bearer' + ' ' + localStorage.getItem('token')
    return config
    },
    error => {
    // 请求错误处理
    console.log('Request Error:', error)
    return Promise.reject(error)
    }
    )

    // 响应拦截器
    service.interceptors.response.use(
    response => {
    // 响应后处理
    if (response.status === 200 && response.data.code === 200) {
    return Promise.resolve(response.data.data)
    } else {
    return Promise.reject(response.data)
    }
    },
    error => {
    console.log('Response Error:', error)
    return Promise.reject(error)
    }
    )

    export default service
    在上面的axios封装中,请求拦截器中添加了一个前置处理,将请求头中添加了一个 Authorization参数,用于后端 token 权限控制。在响应拦截器中添加了一个后置处理,对返回结果进行解析和处理,如果返回结果成功(code值需要和后端协商好)则返回处理后的数据,否则返回处理后的错误信息。

  2. 在 api.js 中引入上面封装的 request.js 文件,并封装所有的 API 请求,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import request from '@/utils/request.js'

    // 用户登录
    export function loginService(data) {
    return request({
    url: '/login',
    method: 'post',
    data
    })
    }
    // 获取用户信息
    export function getUserInfoServie() {
    return request({
    url: '/user/info',
    method: 'get'
    })
    }

  3. 在组件中我们只需要引入 user.js 文件,调用对应的函数即可

    1
    2
    3
    4
    5
    6
    7
    import { loginService,getUserInfoService } from '@/api/user.js'

    const username = ref('')
    const password = ref('')

    const res = await loginService({ username: username.value, password: password.value })
    console.log(res);

跨域问题

所谓跨域,指的是在浏览器发起请求时,请求的目标资源位于另一个域名/端口/协议上,就是跨域。在跨域场景下,浏览器为了保护用户隐私和安全,通常会限制页面在未经允许的情况下访问跨域的资源。

跨域访问的实现需要符合同源策略,即只允许源(协议、域名、端口)相同的网页脚本进行交互操作,否则浏览器会阻止跨域操作,保护用户安全。

在 Vue3 中遇到跨域问题时,可以通过在 vite.config.js 中进行配置来解决。需要在 vite.config.js 中添加 proxy 选项,如下所示:

1
2
3
4
5
6
7
8
9
server:{
proxy:{
'/api':{ //获取路径中包含了/api的请求
target:'http://localhost:8080', //后台服务所在的源
changeOrigin:true, //修改源
rewrite:(path)=>path.replace(/^\/api/,'') //api替换为空字符串
}
}
}
我们将需要解决跨域的 API 的前缀设置为了/api,然后通过 proxy 声明了一个代理规则,将包含/api前缀的请求转发到本地的8080端口,实现解决跨域的效果。其中,changeOrigin设置为true表示修改请求头中的Origin字段为代理服务的地址,避免浏览器发送请求时出现跨域问题,rewrite方法用于去掉请求中的/api前缀