<think>我们基于Vue脚手架创建一个项目,然后集成axios,并实现以下功能:
1. 封装axios实例,设置基础URL和超时时间
2. 添加请求拦截器(前置)和响应拦截器(后置)
3. 封装GET、POST、PUT、DELETE等请求方法
4. 编写多个请求的示例(例如并发请求)
步骤:
1. 创建Vue项目(如果已有可跳过)
2. 安装axios
3. 创建axios实例并封装
4. 在组件中使用封装的请求方法
详细步骤:
### 1. 创建Vue项目
```bash
vue create axios-interceptors-demo
cd axios-interceptors-demo
```
### 2. 安装axios
```bash
npm install axios
```
### 3. 封装axios
在`src`目录下创建`utils/request.js`文件:
```javascript
import axios from 'axios'
// 创建axios实例
const service = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com', // 设置基础URL
timeout: 5000, // 请求超时时间
})
// 请求拦截器(前置)
service.interceptors.request.use(
(config) => {
// 在发送请求之前可以做些什么,例如设置token
// config.headers.Authorization = 'Bearer token'
console.log('请求拦截器:', config)
return config
},
(error) => {
// 对请求错误做些什么
console.log('请求拦截器错误:', error)
return Promise.reject(error)
}
)
// 响应拦截器(后置)
service.interceptors.response.use(
(response) => {
// 对响应数据做点什么,例如只返回data部分
console.log('响应拦截器:', response)
return response.data
},
(error) => {
// 对响应错误做点什么
console.log('响应拦截器错误:', error)
return Promise.reject(error)
}
)
// 封装GET请求
export const get = (url, params) => {
return service.get(url, { params })
}
// 封装POST请求
export const post = (url, data) => {
return service.post(url, data)
}
// 封装PUT请求
export const put = (url, data) => {
return service.put(url, data)
}
// 封装DELETE请求
export const del = (url) => {
return service.delete(url)
}
// 并发请求
export const all = (requests) => {
return axios.all(requests)
}
export default service
```
### 4. 在组件中使用
在`src/views`下创建`AxiosDemo.vue`组件:
```vue
<template>
<div>
<h1>Axios封装示例</h1>
<button @click="handleGet">GET请求</button>
<button @click="handlePost">POST请求</button>
<button @click="handlePut">PUT请求</button>
<button @click="handleDelete">DELETE请求</button>
<button @click="handleConcurrent">并发请求</button>
<pre>{{ responseData }}</pre>
</div>
</template>
<script>
import { get, post, put, del, all } from '@/utils/request'
export default {
data() {
return {
responseData: null
}
},
methods: {
async handleGet() {
try {
const data = await get('/posts/1')
this.responseData = data
} catch (error) {
console.error('GET请求错误:', error)
}
},
async handlePost() {
try {
const data = await post('/posts', {
title: 'foo',
body: 'bar',
userId: 1
})
this.responseData = data
} catch (error) {
console.error('POST请求错误:', error)
}
},
async handlePut() {
try {
const data = await put('/posts/1', {
id: 1,
title: 'updated title',
body: 'updated body',
userId: 1
})
this.responseData = data
} catch (error) {
console.error('PUT请求错误:', error)
}
},
async handleDelete() {
try {
const data = await del('/posts/1')
this.responseData = data
} catch (error) {
console.error('DELETE请求错误:', error)
}
},
async handleConcurrent() {
try {
const requests = [
get('/posts/1'),
get('/posts/2')
]
const responses = await all(requests)
// responses是数组,每个元素是每个请求的结果
this.responseData = responses
} catch (error) {
console.error('并发请求错误:', error)
}
}
}
}
</script>
```
### 5. 添加路由(如果需要)
在`src/router/index.js`中:
```javascript
import Vue from 'vue'
import VueRouter from 'vue-router'
import AxiosDemo from '../views/AxiosDemo.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'AxiosDemo',
component: AxiosDemo
}
]
const router = new VueRouter({
mode: 'history',
routes
})
export default router
```
### 6. 修改App.vue
```vue
<template>
<div id="app">
<router-view/>
</div>
</template>
```
### 7. 运行
```bash
npm run serve
```
### 代码说明
1. **请求封装**:我们将axios实例化,并封装了get、post、put、delete方法,以及并发请求的all方法。
2. **拦截器**:
- 请求拦截器:在请求发出前统一处理(例如添加token)。
- 响应拦截器:在响应后统一处理(例如提取data,或处理错误)。
3. **多请求**:使用`axios.all`处理并发请求。
这样,我们就实现了一个基于Vue脚手架、包含请求封装、拦截器和多请求的axios示例。
### 相关问题
1. 如何在请求拦截器中添加认证token?
2. 响应拦截器中如何处理不同的错误状态码?
3. 如何取消axios请求?
4. axios的并发请求和顺序请求有什么区别?
</think>以下是一个基于 Vue 脚手架的 Axios 请求封装示例,包含请求方式封装、拦截器实现和多请求处理:
### 完整实现方案
#### 1. 安装依赖
```bash
npm install axios
```
#### 2. 封装 Axios 请求 (src/utils/request.js)
```javascript
import axios from 'axios'
// 创建实例
const service = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com',
timeout: 10000
})
// 请求拦截器(前置处理)
service.interceptors.request.use(
config => {
console.log('[请求拦截]', config.url)
// 示例:添加认证令牌
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
// 示例:修改请求数据格式
if (config.method === 'post') {
config.headers['Content-Type'] = 'application/json'
}
return config
},
error => {
console.error('请求拦截出错:', error)
return Promise.reject(error)
}
)
// 响应拦截器(后置处理)
service.interceptors.response.use(
response => {
console.log('[响应拦截]', response.config.url)
// 统一处理响应格式
return response.data
},
error => {
console.error('响应拦截出错:', error)
// 统一错误处理
if (error.response) {
switch (error.response.status) {
case 401:
console.error('未授权,请重新登录')
break
case 403:
console.error('拒绝访问')
break
case 500:
console.error('服务器错误')
break
default:
console.error('未知错误')
}
}
return Promise.reject(error)
}
)
// 封装请求方法
const request = {
get(url, params) {
return service.get(url, { params })
},
post(url, data) {
return service.post(url, data)
},
put(url, data) {
return service.put(url, data)
},
delete(url) {
return service.delete(url)
},
// 并发请求
all(requests) {
return axios.all(requests)
}
}
export default request
```
#### 3. 使用示例 (src/views/AxiosDemo.vue)
```vue
<template>
<div>
<h1>Axios 请求演示</h1>
<button @click="getData">GET 请求</button>
<button @click="postData">POST 请求</button>
<button @click="putData">PUT 请求</button>
<button @click="deleteData">DELETE 请求</button>
<button @click="concurrentRequests">并发请求</button>
<div v-if="loading">加载中...</div>
<pre v-else-if="responseData">{{ responseData }}</pre>
<div v-if="error">{{ error }}</div>
</div>
</template>
<script>
import request from '@/utils/request'
export default {
data() {
return {
loading: false,
responseData: null,
error: null
}
},
methods: {
async getData() {
try {
this.loading = true
this.responseData = await request.get('/posts/1')
} catch (err) {
this.handleError(err)
} finally {
this.loading = false
}
},
async postData() {
try {
this.loading = true
const data = {
title: 'foo',
body: 'bar',
userId: 1
}
this.responseData = await request.post('/posts', data)
} catch (err) {
this.handleError(err)
} finally {
this.loading = false
}
},
async putData() {
try {
this.loading = true
const data = {
id: 1,
title: 'updated title',
body: 'updated body',
userId: 1
}
this.responseData = await request.put('/posts/1', data)
} catch (err) {
this.handleError(err)
} finally {
this.loading = false
}
},
async deleteData() {
try {
this.loading = true
this.responseData = await request.delete('/posts/1')
} catch (err) {
this.handleError(err)
} finally {
this.loading = false
}
},
async concurrentRequests() {
try {
this.loading = true
// 多个并发请求
const results = await request.all([
request.get('/posts/1'),
request.get('/posts/2'),
request.get('/users/1')
])
this.responseData = {
post1: results[0],
post2: results[1],
user1: results[2]
}
} catch (err) {
this.handleError(err)
} finally {
this.loading = false
}
},
handleError(error) {
this.error = `请求失败: ${error.message}`
console.error('API 错误:', error)
}
}
}
</script>
```
### 核心功能说明
#### 1. 请求方式封装
- **四种基本请求方法**:GET/POST/PUT/DELETE
- **统一入口**:所有请求通过`request`对象的方法调用
- **参数处理**:GET请求使用`params`,POST/PUT使用`data`
#### 2. 拦截器实现
1. **请求拦截器**:
- 添加认证令牌(Authorization Header)
- 设置内容类型(Content-Type)
- 记录请求日志
2. **响应拦截器**:
- 提取核心数据(`response.data`)
- 统一错误处理(HTTP状态码处理)
- 异常日志记录
#### 3. 多请求处理
- 使用 `axios.all()` 实现并发请求
- 通过数组接收多个请求结果
- 结构化组织响应数据
#### 4. 组件使用规范
- 统一加载状态管理(loading)
- 错误处理标准化(handleError)
- 响应数据展示(模板渲染)
### 配置路由器 (src/router/index.js)
```javascript
import Vue from 'vue'
import Router from 'vue-router'
import AxiosDemo from '@/views/AxiosDemo'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/axios-demo',
name: 'AxiosDemo',
component: AxiosDemo
}
]
})
```
### 最佳实践建议
1. **环境配置**:在`.env`文件中管理不同环境的API地址
```env:.env.development
VUE_APP_API_BASE_URL = https://dev-api.example.com
```
```javascript:request.js
baseURL: process.env.VUE_APP_API_BASE_URL
```
2. **取消请求**:添加请求取消功能
```javascript
// 创建CancelToken源
const source = axios.CancelToken.source()
// 在请求中配置
request.get('/posts', {
cancelToken: source.token
})
// 取消请求
source.cancel('Operation canceled by user')
```
3. **重试机制**:添加请求失败自动重试
```javascript
service.interceptors.response.use(null, (error) => {
const config = error.config
if (!config || !config.retry) return Promise.reject(error)
config.retryCount = config.retryCount || 0
if (config.retryCount >= config.retry) return Promise.reject(error)
config.retryCount += 1
return new Promise(resolve => {
setTimeout(() => resolve(service(config)), config.retryDelay || 1000)
})
})
```
此实现方案提供了企业级的 Axios 封装模式,可直接用于实际项目开发,具有良好的扩展性和可维护性。