Vue基础知识-脚手架开发-使用Axios发送异步请求+代理服务器解决前后端分离项目的跨域问题
一、为什么会遇到跨域?
在前后端分离开发中,我们常遇到 跨域问题:比如前端 Vue 项目运行在 http://localhost:8080
,后端接口部署在 http://localhost:5000
(或 5001),当前端用 Axios 请求后端接口时,浏览器会因 同源策略 拦截请求(同源需满足:协议、域名、端口三者一致)。
解决跨域的方案有很多,比如后端 CORS、JSONP 等,而 Vue 项目中最常用的是 配置本地代理服务器—— 利用 Vue CLI 的devServer.proxy
,让代理服务器(和前端同端口 8080)转发请求到后端,由于服务器之间不存在同源限制,从而绕过跨域拦截。
二、环境准备
- 安装 Axios:用于发送 HTTP 请求
npm install axios --save
- 后端模拟接口:准备两个后端服务(模拟不同端口的接口)
- 端口 5000:提供学生数据接口 :http://localhost:5000/students
- 端口 5001:提供汽车数据接口 :http://localhost:5000/cars
三、完整代码实现
1. 核心配置:vue.config.js(代理服务器配置)
Vue CLI 的配置文件,用于配置代理、关闭语法检查等,修改后需重启 Vue 项目才生效。
// common.js写法
module.exports = {pages: {index: {entry: 'src/main.js',},},// 关闭语法检查。lintOnSave:false,/* 配置代理服务器(方式一),需要重启VuedevServer: {proxy: 'http://localhost:5000'}, *///配置代理服务器(方式二),需要重启VuedevServer: {proxy: {'/api': {target: 'http://localhost:5000',pathRewrite:{'^/api':''},//表示发请求后将/api变为空ws: true,//使用websoked。默认truechangeOrigin: true//告诉5000服务器请求来自5000,false表示告诉5000服务器(骗)来自8080。默认true},'/car': {target: 'http://localhost:5001',pathRewrite:{'^/car':''},},}}}
2. 入口文件:src/main.js
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 请求的核心逻辑。
<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 axiosimport 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 避免前端资源冲突 | 配置相对复杂 |
方式一配置代码(参考注释)
// 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 ,建议保持默认 |
五、常见问题与注意事项
配置后请求仍失败?
- 必须 重启 Vue 项目!代理配置修改后不会热更新,需重新运行
npm run serve
。
- 必须 重启 Vue 项目!代理配置修改后不会热更新,需重新运行
pathRewrite
为什么必须加?- 若不加,请求
/api/students
会被转发到http://localhost:5000/api/students
,若后端实际接口是/students
,导致 404 错误。 - 加上
pathRewrite: {'^/api': ''}
后,请求会被正确转发到http://localhost:5000/students
。
- 若不加,请求
如何验证代理是否生效?
- 打开浏览器 F12→Network→查看请求的
Request URL
是http://localhost:8080/api/students
(前端端口),而非 5000,说明代理已生效。
- 打开浏览器 F12→Network→查看请求的
前端资源和后端接口同名冲突?
- 例如前端
public
目录下有students资源
,后端有/students
接口:- 方式一代理会优先访问前端的
students
,不走代理; - 方式二通过
/api
前缀区分,可避免冲突(请求/api/students
走代理,请求/students
访问前端资源)。
- 方式一代理会优先访问前端的
- 例如前端