一、AJAX请求方式对比与选型

1. 原生XHR方式

基本使用示例:

缺点分析:

  • 代码冗长复杂

  • 回调地狱问题

  • 需要手动处理JSON转换

  • 错误处理不够直观

2. jQuery的AJAX

基本使用示例:

$.ajax({
  url: 'http://localhost:5000/api/data',
  type: 'GET',
  success: function(data) {
    console.log(data)
  },
  error: function(err) {
    console.error(err)
  }
})

优缺点分析:

  • 优点:

    • 简化了原生XHR的使用

    • 解决了浏览器兼容性问题

    • 提供了丰富的配置选项

  • 缺点:

    • 引入了整个jQuery库,体积较大

    • 不符合现代前端开发趋势(Vue/React不推荐操作DOM)

    • 回调方式不如Promise直观

3. Fetch API

基本使用示例:

fetch('http://localhost:5000/api/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok')
    }
    return response.json()
  })
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error))

优缺点分析:

  • 优点:

    • 浏览器原生支持,无需额外库

    • 基于Promise的现代API

    • 更简洁的语法

  • 缺点:

    • IE浏览器完全不支持

    • 需要手动处理JSON转换

    • 错误处理不够直观(不会reject HTTP错误状态)

    • 功能相对简单,缺少拦截器等高级功能

4. Axios

基本使用示例:

axios.get('http://localhost:5000/api/data')
  .then(response => console.log(response.data))
  .catch(error => console.error('Error:', error))

优势分析:

  1. Promise风格:解决了回调地狱问题

  2. 浏览器/Node.js通用:同构API设计

  3. 丰富的功能:

    • 拦截请求和响应

    • 转换请求和响应数据

    • 自动JSON数据转换

    • 客户端支持防御XSRF

  4. 更好的错误处理:会reject HTTP错误状态

  5. 活跃的社区支持:持续维护更新

选型结论:在Vue项目中推荐使用Axios作为HTTP客户端

二、Axios的安装与使用详解

1. 安装Axios

npm install axios
# 或
yarn add axios

2. 基本使用方式

2.1 发起GET请求
import axios from 'axios'

// 方式一:直接使用axios对象
axios.get('/user?ID=12345')
  .then(response => console.log(response.data))
  .catch(error => console.error(error))

// 方式二:使用config对象
axios({
  method: 'get',
  url: '/user',
  params: {
    ID: 12345
  }
})
.then(response => console.log(response.data))
2.2 发起POST请求
axios.post('/user', {
  firstName: 'Fred',
  lastName: 'Flintstone'
})
.then(response => console.log(response.data))
2.3 并发请求
const getUser = axios.get('/user/12345')
const getPermissions = axios.get('/user/12345/permissions')

axios.all([getUser, getPermissions])
  .then(axios.spread((userResp, permResp) => {
    console.log(userResp.data, permResp.data)
  }))

3. 高级配置

3.1 创建实例
const api = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
})
3.2 请求拦截器
axios.interceptors.request.use(config => {
  // 在发送请求前添加token
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})
3.3 响应拦截器
axios.interceptors.response.use(
  response => response.data, // 直接返回data字段
  error => {
    if (error.response.status === 401) {
      // 处理未授权错误
      router.push('/login')
    }
    return Promise.reject(error)
  }
)

三、跨域问题解析

1. 跨域现象与原理

同源策略限制的三要素:

  1. 协议相同(http/https)

  2. 主机名相同(localhost/example.com)

  3. 端口号相同(8080/5000)

跨域错误提示:

Access to XMLHttpRequest at 'http://localhost:5000/api' from origin 'http://localhost:8080' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

实际请求过程:

  1. 浏览器发送实际请求前会先发送OPTIONS预检请求

  2. 服务端需要响应预检请求,声明允许的跨域策略

  3. 只有预检通过后,浏览器才会发送真正的请求

2. 跨域解决方案对比

方案实现方式优点缺点适用场景
CORS服务端设置响应头官方标准,前端无需额外处理需要服务端支持生产环境,可控的服务端
JSONP动态创建script标签兼容老浏览器仅支持GET,安全性低需要支持老系统的场景
代理服务器前端服务转发请求前端无需修改,开发环境友好生产环境需要Nginx配置开发环境,前后端分离项目

四、Vue代理方案详解

1. 代理原理说明

浏览器 (http://localhost:8080)
  → Vue开发服务器 (http://localhost:8080)
    → 实际API服务器 (http://localhost:5000)

 代理服务器充当中间人角色,利用服务端请求不受同源策略限制的特性解决跨域问题。

2. 配置方法

2.1 简单配置(方案一)

vue.config.js:

module.exports = {
  devServer: {
    proxy: 'http://localhost:5000'
  }
}

特点:

  • 所有请求都会被代理到目标服务器

  • 无法配置多个后端服务

  • 会优先匹配本地存在的文件

2.2 高级配置(方案二)

vue.config.js:

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:5000', // 目标服务器
        pathRewrite: {'^/api': ''},     // 重写路径
        changeOrigin: true,             // 修改请求头中的host
        ws: true                        // 支持websocket
      },
      '/api2': {
        target: 'http://localhost:5001',
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}

配置项说明:

  • target:代理目标地址

  • pathRewrite:路径重写规则

  • changeOrigin:修改请求头中的host值(true时,host会被设置为target)

  • ws:是否代理websocket连接

3. 前端请求示例

// 请求会被代理到 http://localhost:5000/user
axios.get('/api/user')
  .then(response => console.log(response.data))

// 另一个服务的请求会被代理到 http://localhost:5001/order
axios.get('/api2/order')
  .then(response => console.log(response.data))

4. 生产环境部署

开发环境使用Vue代理,生产环境推荐使用Nginx反向代理:

server {
  listen 80;
  server_name example.com;
  
  location /api {
    proxy_pass http://localhost:5000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
  
  location / {
    root /path/to/dist;
    try_files $uri $uri/ /index.html;
  }
}

五、最佳实践建议

  1. 开发环境:

    • 使用Vue代理方案二

    • 为不同后端服务配置不同前缀

    • 启用changeOrigin避免某些服务器的host校验

  2. 生产环境:

    • 使用Nginx反向代理

    • 配置合适的CORS策略(如需)

    • 启用HTTPS加密通信

  3. Axios使用:

    • 封装统一的请求实例

    • 添加拦截器处理通用逻辑

    • 对API进行模块化管理

    • 统一错误处理机制

  4. 安全考虑:

    • 生产环境限制CORS来源

    • 敏感接口添加身份验证

    • 对代理转发的请求进行适当过滤

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐