返回

XMLHttpRequest、Axios 与 Fetch 在 Vue3 中的深度解析

XMLHttpRequest (XHR)基于回调函数,易产生回调地狱

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();

代码解析

  1. open()方法
    • 第三个参数true表示异步请求
    • readyState状态(标识XMLHttpRequest对象处于什么状态)说明:
      • 0: 未初始化
      • 1: 已建立连接
      • 2: 请求已接收
      • 3: 处理中
      • 4: 完成
  2. 手动处理JSON:需通过JSON.parse()转换响应文本
  3. 错误处理缺失:未处理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));

代码解析

  1. response.ok:自动判断2xx状态码
  2. .json()方法:返回Promise对象,自动解析JSON
  3. 错误处理
    • .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项目推荐方案

  1. 小型项目fetch + 组合式API封装
  2. 中大型项目:Axios实例 + Pinia状态管理
  3. SSR项目:Nuxt3的useFetch组合式函数
  4. TypeScript项目:Axios + 类型守卫

提示:在Vue3.2+版本中,推荐使用<script setup>语法配合组合式API进行开发,可获得更好的类型推导支持。

使用 Hugo 构建
主题 StackJimmy 设计