Vue网络请求 Axios的基本使用与配置详解
一、Axios 简介
Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js。它能让前端开发者更方便地与后端服务器进行数据交互,无论是发送 HTTP 请求获取数据,还是将数据提交到服务器。在 Vue 项目中,Axios 是最常用的网络请求库之一,它具有以下优点:
- 支持 Promise API:Promise 使得异步操作的代码更加简洁和易于维护,避免了传统回调函数带来的回调地狱问题。
- 浏览器和 Node.js 通用:无论是在前端浏览器环境还是后端 Node.js 环境,Axios 都能良好地运行,方便进行全栈开发。
- 自动转换 JSON 数据:Axios 会自动将响应数据转换为 JSON 格式,这样在处理数据时更加方便。
- 请求和响应拦截:可以在请求发送前和响应接收后进行一些通用的操作,如添加请求头、验证响应数据等。
二、安装 Axios
在 Vue 项目中使用 Axios,首先需要安装它。如果你的项目使用 npm 作为包管理器,可以在项目根目录下执行以下命令:
npm install axios --save
如果使用 yarn,则执行:
yarn add axios
安装完成后,Axios 就可以在项目中使用了。
三、基本使用
- 简单的 GET 请求
在 Vue 组件中发起一个简单的 GET 请求获取数据非常容易。假设我们有一个后端 API 接口
/api/users
,它返回用户列表数据。在 Vue 组件的created
钩子函数中发起请求:
<template>
<div>
<ul>
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
users: []
};
},
created() {
axios.get('/api/users')
.then(response => {
this.users = response.data;
})
.catch(error => {
console.error('Error fetching users:', error);
});
}
};
</script>
在上述代码中,axios.get('/api/users')
发起了一个 GET 请求到 /api/users
接口。当请求成功时,.then
回调函数会被执行,response.data
就是从服务器返回的数据,我们将其赋值给组件的 users
数据属性,然后在模板中进行展示。如果请求失败,.catch
回调函数会捕获到错误并在控制台打印错误信息。
2. 带参数的 GET 请求
有时候我们需要在 GET 请求中传递参数。例如,我们有一个 /api/posts
接口,它可以根据 category
参数返回特定分类的文章列表。可以这样发起请求:
axios.get('/api/posts', {
params: {
category: 'tech'
}
})
.then(response => {
this.posts = response.data;
})
.catch(error => {
console.error('Error fetching posts:', error);
});
在 axios.get
的第二个参数中,通过 params
对象来传递参数。Axios 会自动将这些参数拼接到 URL 中,最终请求的 URL 可能是 /api/posts?category=tech
。
3. POST 请求
发起 POST 请求用于向服务器提交数据。假设我们有一个 /api/register
接口用于用户注册,需要传递 username
和 password
数据:
<template>
<div>
<form @submit.prevent="register">
<label for="username">Username:</label>
<input type="text" id="username" v-model="username">
<br>
<label for="password">Password:</label>
<input type="password" id="password" v-model="password">
<br>
<button type="submit">Register</button>
</form>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
username: '',
password: ''
};
},
methods: {
register() {
axios.post('/api/register', {
username: this.username,
password: this.password
})
.then(response => {
console.log('Registration successful:', response.data);
})
.catch(error => {
console.error('Registration failed:', error);
});
}
}
};
</script>
在 axios.post
中,第一个参数是请求的 URL,第二个参数是要提交的数据对象。服务器接收到数据后可以进行相应的处理,如保存用户信息到数据库等。
四、Axios 配置
- 全局配置
Axios 允许我们进行全局配置,这些配置会应用到所有通过 Axios 发起的请求中。在 Vue 项目的入口文件(通常是
main.js
)中进行全局配置:
import axios from 'axios';
import Vue from 'vue';
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token');
axios.defaults.headers.post['Content-Type'] = 'application/json';
Vue.prototype.$http = axios;
- baseURL:设置了所有请求的基础 URL。例如,后续发起
axios.get('/users')
请求,实际请求的 URL 会是https://api.example.com/users
。这样在开发和部署时,如果 API 服务器地址发生变化,只需要修改baseURL
一处即可。 - headers:设置请求头。这里在
common
类型的请求头中添加了Authorization
字段,用于进行身份验证,值是从本地存储中获取的token
。同时,针对post
请求,设置了Content-Type
为application/json
,表示提交的数据是 JSON 格式。
- 实例配置 除了全局配置,我们还可以创建 Axios 的实例,并为实例进行单独的配置。这样可以在不同的场景下使用不同配置的 Axios 实例。
import axios from 'axios';
const instance = axios.create({
baseURL: 'https://another-api.example.com',
timeout: 5000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
instance.get('/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error);
});
- create 方法:通过
axios.create
方法创建了一个新的 Axios 实例instance
。 - 配置参数:
baseURL
:为该实例设置了不同的基础 URL。timeout
:设置请求超时时间为 5000 毫秒(5 秒)。如果请求在 5 秒内没有得到响应,就会触发超时错误。headers
:设置了该实例的请求头,这里将Content-Type
设置为application/x-www-form-urlencoded
,适用于以表单形式提交数据的情况。
- 请求配置 在每次发起请求时,也可以单独设置请求的配置。这些配置会覆盖全局配置和实例配置中相同的部分。
axios.get('/specific-data', {
baseURL: 'https://special-api.example.com',
headers: {
'X-Custom-Header': 'Some value'
},
params: {
key: 'value'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error);
});
在这个 get
请求中,通过第二个参数设置了请求的配置。这里的 baseURL
会覆盖全局和实例配置中的 baseURL
,headers
中添加了自定义的 X - Custom - Header
头信息,params
用于传递请求参数。
五、请求和响应拦截器
- 请求拦截器 请求拦截器可以在请求发送之前对请求进行一些处理,如添加加载动画、设置请求头、验证参数等。在全局配置中添加请求拦截器:
import axios from 'axios';
axios.interceptors.request.use(config => {
// 显示加载动画
console.log('Starting request...');
// 添加自定义请求头
config.headers['X - Request - From'] = 'Vue App';
return config;
}, error => {
return Promise.reject(error);
});
axios.interceptors.request.use
:该方法用于添加请求拦截器。它接受两个回调函数作为参数。- 第一个回调函数:在请求发送前被调用,
config
是请求的配置对象。在这里我们可以对config
进行修改,如添加自定义请求头。同时,我们在控制台打印信息模拟显示加载动画的操作。 - 第二个回调函数:如果请求拦截过程中出现错误,会调用这个回调函数,我们将错误通过
Promise.reject
抛出。
- 响应拦截器 响应拦截器可以在接收到响应后对响应进行处理,如隐藏加载动画、验证响应数据、处理错误等。同样在全局配置中添加响应拦截器:
axios.interceptors.response.use(response => {
// 隐藏加载动画
console.log('Request completed.');
return response;
}, error => {
if (error.response) {
// 处理 401 未授权错误
if (error.response.status === 401) {
console.log('Unauthorized. Please login again.');
}
}
return Promise.reject(error);
});
axios.interceptors.response.use
:用于添加响应拦截器,也接受两个回调函数。- 第一个回调函数:在响应成功时被调用,
response
是服务器返回的响应对象。我们在这里模拟隐藏加载动画的操作,并直接返回response
,这样后续的.then
回调函数就能接收到正常的响应数据。 - 第二个回调函数:当响应出现错误时被调用,
error
包含了错误信息。如果error
中有response
属性,说明是服务器返回了错误状态码。这里我们针对401
未授权错误进行了特殊处理,在控制台打印提示信息。最后将错误通过Promise.reject
抛出,以便在请求的.catch
回调函数中进一步处理。
六、并发请求
有时候我们需要同时发起多个请求,并在所有请求都完成后进行一些操作。Axios 提供了 axios.all
和 axios.spread
方法来处理并发请求。
假设我们有两个 API 接口 /api/users
和 /api/posts
,分别获取用户列表和文章列表。我们希望在获取到这两个数据后再进行展示:
<template>
<div>
<h2>Users</h2>
<ul>
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
<h2>Posts</h2>
<ul>
<li v-for="post in posts" :key="post.id">{{ post.title }}</li>
</ul>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
users: [],
posts: []
};
},
created() {
const userRequest = axios.get('/api/users');
const postRequest = axios.get('/api/posts');
axios.all([userRequest, postRequest])
.then(axios.spread((userResponse, postResponse) => {
this.users = userResponse.data;
this.posts = postResponse.data;
}))
.catch(error => {
console.error('Error:', error);
});
}
};
</script>
axios.all
:接受一个包含多个 Axios 请求的数组作为参数。它返回一个新的 Promise,这个 Promise 在数组中的所有请求都完成后才会 resolve。axios.spread
:用于将axios.all
返回的 Promise 的多个响应数据解构为单独的参数。在上述代码中,userResponse
是/api/users
请求的响应,postResponse
是/api/posts
请求的响应。我们将它们的数据分别赋值给组件的users
和posts
属性,然后在模板中展示。
七、处理错误
在使用 Axios 进行网络请求时,可能会遇到各种错误。前面我们已经在一些示例中简单处理了错误,这里详细介绍一下错误类型和处理方法。
- 网络错误
当网络连接出现问题,如网络中断、服务器无响应等,Axios 会抛出一个错误,
error.message
会包含错误信息。
axios.get('/api/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
if (!error.response) {
console.error('Network error:', error.message);
}
});
在这个例子中,通过检查 error.response
是否存在来判断是否是网络错误。如果不存在,则说明是网络问题,打印网络错误信息。
2. HTTP 错误状态码
当服务器返回的 HTTP 状态码表示错误时,如 404(未找到)、500(服务器内部错误)等,Axios 也会抛出错误。error.response
中包含了响应的详细信息,如状态码、响应头和响应体等。
axios.get('/api/nonexistent - data')
.then(response => {
console.log(response.data);
})
.catch(error => {
if (error.response) {
console.error('HTTP error:', error.response.status, error.response.data);
}
});
这里通过 error.response.status
获取状态码,error.response.data
获取服务器返回的错误信息,从而更好地处理不同类型的 HTTP 错误。
3. 请求取消错误
有时候我们可能需要取消正在进行的请求,如用户在请求还未完成时切换了页面。Axios 提供了取消请求的功能。
import axios, { CancelToken } from 'axios';
const source = CancelToken.source();
axios.get('/api/data', {
cancelToken: source.token
})
.then(response => {
console.log(response.data);
})
.catch(error => {
if (axios.isCancel(error)) {
console.log('Request canceled:', error.message);
} else {
console.error('Error:', error);
}
});
// 取消请求
source.cancel('User canceled the request');
CancelToken.source()
:创建一个取消令牌源source
,source.token
可以传递给 Axios 请求作为cancelToken
参数。source.cancel(message)
:调用cancel
方法取消请求,message
会作为错误信息传递。在.catch
回调函数中,通过axios.isCancel(error)
判断是否是取消请求的错误,并打印相应的信息。
八、Axios 与 Vuex 的结合使用
在大型 Vue 项目中,通常会使用 Vuex 进行状态管理。Axios 与 Vuex 结合可以更好地处理数据的获取、存储和更新。
- 在 Vuex 中定义 actions
假设我们有一个模块用于管理用户数据,在
store/modules/user.js
中定义获取用户列表的 action:
import axios from 'axios';
const state = {
users: []
};
const mutations = {
SET_USERS(state, users) {
state.users = users;
}
};
const actions = {
async fetchUsers({ commit }) {
try {
const response = await axios.get('/api/users');
commit('SET_USERS', response.data);
} catch (error) {
console.error('Error fetching users:', error);
}
}
};
export default {
state,
mutations,
actions
};
actions
中的fetchUsers
:这是一个异步 action,使用async/await
语法来处理 Axios 请求。通过await axios.get('/api/users')
发起请求并等待响应。如果请求成功,将响应数据通过commit
提交给SET_USERS
mutation 来更新state.users
。如果请求失败,捕获错误并在控制台打印。
- 在 Vue 组件中调用 action
在 Vue 组件中可以通过
this.$store.dispatch
来调用fetchUsers
action:
<template>
<div>
<ul>
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
users: []
};
},
created() {
this.$store.dispatch('fetchUsers').then(() => {
this.users = this.$store.state.user.users;
});
}
};
</script>
在组件的 created
钩子函数中,调用 this.$store.dispatch('fetchUsers')
触发获取用户列表的操作。当 action 执行完成后,从 Vuex 的 state
中获取更新后的用户列表并赋值给组件的 users
属性进行展示。
九、Axios 的性能优化
- 合理设置超时时间
如前文所述,通过设置
timeout
参数可以避免请求长时间等待,消耗资源。根据业务场景合理设置超时时间,既保证请求有足够时间完成,又不会在服务器无响应时一直等待。例如,对于一些实时性要求不高但数据量较大的请求,可以适当延长超时时间;而对于一些简单的查询请求,可以设置较短的超时时间。 - 缓存数据 如果某些数据在一定时间内不会发生变化,可以考虑进行缓存。例如,使用浏览器的本地存储或 Vuex 的状态缓存来存储请求结果。在发起请求前先检查缓存中是否有数据,如果有且未过期,则直接使用缓存数据,避免重复请求服务器。
// 检查本地存储中是否有缓存的用户数据
const cachedUsers = localStorage.getItem('cachedUsers');
if (cachedUsers) {
this.users = JSON.parse(cachedUsers);
} else {
axios.get('/api/users')
.then(response => {
this.users = response.data;
// 将用户数据缓存到本地存储
localStorage.setItem('cachedUsers', JSON.stringify(response.data));
})
.catch(error => {
console.error('Error fetching users:', error);
});
}
- 合并请求 如果在短时间内需要发起多个相似的请求,可以考虑将这些请求合并为一个。例如,在一个页面中需要获取用户信息、用户的订单列表和用户的收藏列表,可以通过一个 API 接口一次性返回这些数据,而不是分别发起三个请求。这样可以减少网络请求次数,提高性能。
十、Axios 在跨域场景下的应用
- 什么是跨域
当浏览器向一个不同源(协议、域名、端口号三者有一个不同即为不同源)的服务器发起请求时,就会出现跨域问题。这是浏览器出于安全考虑的一种机制,会阻止 JavaScript 代码获取跨域请求的响应数据。例如,前端页面在
http://localhost:8080
运行,而 API 服务器在http://api.example.com
,此时发起请求就会产生跨域问题。 - 解决跨域的方法
- CORS(跨域资源共享):这是最常用的解决跨域问题的方法。服务器端需要设置响应头来允许跨域请求。例如,在 Node.js 中使用 Express 框架,可以通过
cors
中间件来实现:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
// 其他路由和处理逻辑
这样服务器就会允许来自任何源的跨域请求。也可以通过配置 cors
中间件来限制允许的源,如:
app.use(cors({
origin: 'http://localhost:8080'
}));
只允许 http://localhost:8080
这个源的请求。
- 代理:在开发环境中,可以使用代理来解决跨域问题。在 Vue 项目中,可以通过修改
vue.config.js
文件来配置代理:
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://api.example.com',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
};
这里配置了将以 /api
开头的请求代理到 http://api.example.com
。changeOrigin
设置为 true
表示修改请求头中的 origin
字段,使其看起来像是从目标服务器发出的请求。pathRewrite
用于重写路径,将 /api
前缀去掉,这样实际请求的 URL 就是目标服务器上正确的路径。
通过以上对 Axios 的基本使用、配置、与其他技术结合以及性能优化等方面的详细介绍,相信开发者能够在 Vue 项目中更加熟练、高效地使用 Axios 进行网络请求开发。无论是小型项目还是大型应用,Axios 都能为前端与后端的数据交互提供强大而便捷的支持。在实际开发中,根据项目的具体需求和场景,灵活运用 Axios 的各种特性,能够提升项目的质量和用户体验。同时,随着技术的不断发展和项目的演进,持续关注 Axios 的更新和优化,以适应不断变化的开发需求。在处理复杂业务逻辑和高并发场景时,合理运用 Axios 的并发请求、请求和响应拦截器等功能,能够更好地组织代码和管理数据。在面对跨域等常见问题时,选择合适的解决方案确保项目的顺利进行。总之,Axios 作为 Vue 开发中网络请求的重要工具,值得开发者深入学习和掌握。