Vue基础知识-脚手架开发-使用Axios发送异步请求+代理服务器解决前后端分离项目的跨域问题

一、为什么会遇到跨域?

在前后端分离开发中,我们常遇到 跨域问题 :比如前端 Vue 项目运行在 http://localhost:8080,后端接口部署在 http://localhost:5000(或 5001),当前端用 Axios 请求后端接口时,浏览器会因 同源策略 拦截请求(同源需满足:协议、域名、端口三者一致)。

解决跨域的方案有很多,比如后端 CORS、JSONP 等,而 Vue 项目中最常用的是 配置本地代理服务器 ------ 利用 Vue CLI 的devServer.proxy,让代理服务器(和前端同端口 8080)转发请求到后端,由于服务器之间不存在同源限制,从而绕过跨域拦截。

二、环境准备

  1. 安装 Axios :用于发送 HTTP 请求

    复制代码
    npm install axios --save
  2. 后端模拟接口 :准备两个后端服务(模拟不同端口的接口)

三、完整代码实现

1. 核心配置:vue.config.js(代理服务器配置)

Vue CLI 的配置文件,用于配置代理、关闭语法检查等,修改后需重启 Vue 项目才生效

javascript 复制代码
// common.js写法
module.exports = {
    pages: {
      index: {
        entry: 'src/main.js',
      },
    },
    // 关闭语法检查。
    lintOnSave:false,
    /* 
    配置代理服务器(方式一),需要重启Vue
      devServer: {
        proxy: 'http://localhost:5000'
    }, 
    */
   //配置代理服务器(方式二),需要重启Vue
    devServer: {
      proxy: {
        '/api': {
          target: 'http://localhost:5000',
          pathRewrite:{'^/api':''},//表示发请求后将/api变为空
          ws: true,//使用websoked。默认true
          changeOrigin: true//告诉5000服务器请求来自5000,false表示告诉5000服务器(骗)来自8080。默认true
        },
        '/car': {
          target: 'http://localhost:5001',
          pathRewrite:{'^/car':''},
        },
      }
    }
  }

2. 入口文件:src/main.js

javascript 复制代码
import Vue from 'vue'
//引入App组件
import App from './App.vue'
//关闭生产提示
Vue.config.productionTip = false
//创建vm
new Vue({
    //将App组件放入容器(帮你挂到public/index.html)
    render: h => h(App),

}).$mount('#app')//挂载。和配置el选项一样

3. 核心组件:src/App.vue(请求逻辑 + 页面渲染)

实现按钮点击请求数据、表格渲染,以及 Axios 请求的核心逻辑。

html 复制代码
<template>
    <div>
        <input type="button" value="获取学生数据" @click="getStudents"/><br><br>
  
        <table  border="1px solid black">
            <tr>
                <td>id</td>
                <td>姓名</td>
                <td>年龄</td>
            </tr>
            <tr v-for="student in students" :key="student.id">
                <td>{{student.id}}</td>
                <td>{{student.name}}</td>
                <td>{{student.age}}</td>
            </tr>
        </table>
        <hr>    
        <input type="button" value="获取汽车数据" @click="getCars"/><br><br>
        <table  border="1px solid black">
            <tr>
                <td>id</td>
                <td>名称</td>
                <td>价格</td>
            </tr>
            <tr v-for="car in cars" :key="car.id">
                <td>{{car.id}}</td>
                <td>{{car.name}}</td>
                <td>{{car.price}}</td>
            </tr>
        </table>
        
    </div>
</template>

<script>
    //npm install axios
    import axios from 'axios'
    export default {
        name:'App',
        data() {
            return {
                students:[],
                cars:[]
            }
        },
        components:{
             
        },
        methods:{
            /* 
                遇到跨域问题:浏览器使用XMLHttpRequest访问服务器时有同源策略限制
                解决跨域问题:开启代理服务器(端口也是8080)。让代理服务器去和5000服务器拿数据。服务器之间数据交互直接使用http。没有同源限制
             */
            getStudents(){
                /* 
                 配置代理服务器(方式一)
                     1 开启代理服务器后这里的请求端口直接写8080。
                          http://localhost:8080/students后面会解析成http://localhost:5000/students(只换端口)
                     2 若8080本身就有http://localhost:8080/students资源(例如public目录下有一个students)。就不会走代理服务器
                     3 不能配置多个代理
                代码如下:
                axios.get('http://localhost:8080/students').then( 
                     response =>{
                           this.students = response.data
                     },
                    error =>{
                         console.log(error.message)
                      }
                )
                */

                /* 
                配置代理服务器(方式二)
                    1 可以解决第一种配置方法的第二,三点注意事项。
                    2 配置pathRewrite:{'^/api':''}后。最终发送请求为http://localhost:5000/students
                */
                axios.get('http://localhost:8080/api/students').then( 
                    response =>{
                        console.log(response.data)
                        this.students = response.data //直接返回对象数组了
                    },
                    error =>{
                        console.log(error.message)
                    }
                )
            },
            getCars(){
                axios.get('http://localhost:8080/car/cars').then( 
                    response =>{
                        this.cars = response.data
                    },
                    error =>{
                        console.log(error.message)
                    }
                )
            }
        }
    }
</script>

<style>
   
</style>

四、知识点

1. 代理的核心原理

  • 前端(8080)→ 代理服务器(8080,和前端同域)→ 后端接口(5000/5001)
  • 由于代理服务器和前端同域,不存在跨域问题;而服务器之间的请求(代理→后端)不受浏览器同源策略限制,因此实现跨域请求。

2. 两种代理配置方式对比

配置方式 适用场景 优点 缺点
方式一(单代理) 仅需转发到一个后端地址(如仅 5000 端口) 配置简单,一行代码 无法同时转发到多个后端;若前端有同名接口(如 /public/students),会优先访问前端资源,不走代理
方式二(多代理) 需转发到多个后端地址(如 5000 和 5001) 支持多代理;可通过pathRewrite避免前端资源冲突 配置相对复杂
方式一配置代码(参考注释)
javascript 复制代码
// vue.config.js 方式一配置
devServer: {
  proxy: 'http://localhost:5000' // 所有请求都转发到5000端口
}

使用时,请求地址直接写http://localhost:8080/students,代理会自动转发到http://localhost:5000/students

3. 关键配置参数说明

参数 作用 取值
target 后端接口的基础地址(真实要转发的地址) http://localhost:5000
pathRewrite 路径重写(核心!) 例如{'^/api': ''}:将请求中的/api前缀替换为空,避免后端接收多余的/api
ws 是否支持 WebSocket(如实时通信) 默认true,无需修改
changeOrigin 是否 "欺骗" 后端请求来源 true:告诉后端 "请求来自target地址(5000)";false:告诉后端真实来源(8080);默认true,建议保持默认

五、常见问题与注意事项

  1. 配置后请求仍失败?

    • 必须 重启 Vue 项目 !代理配置修改后不会热更新,需重新运行npm run serve
  2. pathRewrite为什么必须加?

    • 若不加,请求/api/students会被转发到http://localhost:5000/api/students,若后端实际接口是/students,导致 404 错误。
    • 加上pathRewrite: {'^/api': ''}后,请求会被正确转发到http://localhost:5000/students
  3. 如何验证代理是否生效?

    • 打开浏览器 F12→Network→查看请求的Request URLhttp://localhost:8080/api/students(前端端口),而非 5000,说明代理已生效。
  4. 前端资源和后端接口同名冲突?

    • 例如前端public目录下有students资源,后端有/students接口:
      • 方式一代理会优先访问前端的students,不走代理;
      • 方式二通过/api前缀区分,可避免冲突(请求/api/students走代理,请求/students访问前端资源)。
相关推荐
叫我阿柒啊2 小时前
从Java全栈到前端框架:一次真实的面试对话与技术解析
java·javascript·typescript·vue·springboot·react·前端开发
张迅之3 小时前
【React】Ant Design 5.x 实现tabs圆角及反圆角效果
前端·react.js·ant-design
@CLoudbays_Martin113 小时前
为什么动态视频业务内容不可以被CDN静态缓存?
java·运维·服务器·javascript·网络·python·php
蔗理苦4 小时前
2025-09-05 CSS3——盒子模型
前端·css·css3
二川bro5 小时前
第25节:VR基础与WebXR API入门
前端·3d·vr·threejs
上单带刀不带妹5 小时前
Node.js 的模块化规范是什么?CommonJS 和 ES6 模块有什么区别?
前端·node.js·es6·模块化
缘如风5 小时前
easyui 获取自定义的属性
前端·javascript·easyui
诗书画唱5 小时前
【前端教程】JavaScript 实现图片鼠标悬停切换效果与==和=的区别
开发语言·前端·javascript
光影少年5 小时前
前端上传切片优化以及实现
前端·javascript·掘金·金石计划