XMLHttpRequest、Axios 与 Fetch 在 Vue3 中的深度解析
一、XMLHttpRequest (XHR)
核心特性
- 历史地位:Web 2.0时代的核心技术,实现AJAX异步请求
- 兼容性:支持IE6+等老旧浏览器
- 缺陷:基于回调函数,易产生回调地狱
基础示例
1
2
3
4
5
6
7
8
9
10
11
12
13
|
const xhr = new XMLHttpRequest();
// 1. 初始化请求(方法、URL、异步标志)
xhr.open('GET', '/api/data', true);
// 2. 监听状态变化事件
xhr.onreadystatechange = function() {
// 3. 判断请求完成且状态码200
if (xhr.readyState === 4 && xhr.status === 200) {
// 4. 手动解析JSON响应
console.log(JSON.parse(xhr.responseText));
}
};
// 5. 发送请求
xhr.send();
|
代码解析
open()
方法:
- 第三个参数
true
表示异步请求
readyState
状态(标识XMLHttpRequest对象处于什么状态)说明:
- 0: 未初始化
- 1: 已建立连接
- 2: 请求已接收
- 3: 处理中
- 4: 完成
- 手动处理JSON:需通过
JSON.parse()
转换响应文本
- 错误处理缺失:未处理4xx/5xx状态码
GET和POST请求数据区别
使用Get请求时,参数在URL中显示,而使用Post方式,则放在send里面
使用Get请求发送数据量小,Post请求发送数据量大
使用Get请求安全性低,会被缓存,而Post请求反之 关于第一点区别,详情见下面两张图:

参考文献:Ajax原理一篇就够了
二、Fetch API
核心特性
- 现代标准:基于Promise的链式调用
- 简洁语法:支持async/await
- 注意点:默认不携带cookie
基础示例
1
2
3
4
5
6
7
8
|
fetch('/api/data')
.then(response => {
// 手动处理非2xx状态码
if (!response.ok) throw new Error('HTTP error');
return response.json(); // 自动解析JSON
})
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
|
代码解析
response.ok
:自动判断2xx状态码
.json()
方法:返回Promise对象,自动解析JSON
- 错误处理:
.catch()
捕获网络错误
- 需手动处理业务错误(如404)
Vue3整合示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
import { ref, onMounted } from 'vue';
export default {
setup() {
const data = ref(null);
onMounted(async () => {
try {
// 使用async/await简化代码
const response = await fetch('/api/data');
data.value = await response.json();
} catch (error) {
console.error('Fetch Error:', error);
}
});
return { data };
}
};
|
三、Axios
核心特性
- 功能丰富:拦截器、自动JSON转换
- 跨平台:支持浏览器和Node.js
- 生态集成:与Vue3深度适配
基础示例
1
2
3
4
5
6
|
axios.get('/api/data')
.then(response => console.log(response.data))
.catch(error => {
// 统一错误处理
console.error(error.response?.data || error.message);
});
|
高级用法:创建实例
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
|
// src/api/index.js
import axios from 'axios';
const apiClient = axios.create({
baseURL: import.meta.env.VITE_API_URL,
timeout: 5000,
headers: {'X-Custom-Header': 'foobar'}
});
// 请求拦截器
apiClient.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});
// 响应拦截器
apiClient.interceptors.response.use(
response => response.data,
error => {
if (error.response.status === 401) {
// 统一处理未授权错误
router.push('/login');
}
return Promise.reject(error);
}
);
export default apiClient;
|
四、Vue3最佳实践
1. 组合式API封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import { ref } from 'vue';
export function useFetch(url) {
const data = ref(null);
const loading = ref(false);
const error = ref(null);
const fetchData = async () => {
try {
loading.value = true;
const response = await fetch(url);
data.value = await response.json();
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
};
return { data, loading, error, fetchData };
}
|
2. Pinia状态管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
// stores/posts.js
import { defineStore } from 'pinia';
import axios from 'axios';
export const usePostStore = defineStore('posts', {
state: () => ({
posts: [],
loading: false,
error: null
}),
actions: {
async fetchPosts() {
this.loading = true;
try {
const res = await axios.get('/api/posts');
this.posts = res.data;
} catch (error) {
this.error = error.message;
} finally {
this.loading = false;
}
}
}
});
|
五、技术选型对比表
特性 |
XMLHttpRequest |
Fetch |
Axios |
语法复杂度 |
⭐️(回调地狱) |
⭐️⭐️⭐️(Promise) |
⭐️⭐️⭐️⭐️(链式调用) |
浏览器兼容性 |
IE6+ |
IE10+ |
IE11+ |
自动JSON转换 |
❌ |
✅ |
✅ |
拦截器支持 |
❌ |
❌ |
✅ |
取消请求 |
手动实现 |
✅(AbortController) |
✅ |
默认携带Cookie |
❌ |
❌ |
✅ |
六、Vue3项目推荐方案
- 小型项目:
fetch
+ 组合式API封装
- 中大型项目:Axios实例 + Pinia状态管理
- SSR项目:Nuxt3的
useFetch
组合式函数
- TypeScript项目:Axios + 类型守卫
提示:在Vue3.2+版本中,推荐使用<script setup>
语法配合组合式API进行开发,可获得更好的类型推导支持。