vue3 + axios 跨域问题解决方案
1. 报错情况如下
控制台报错:Access to XMLHttpRequest at 'http://xxx' from origin 'http://xxx' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
2. 出现原因
出于浏览器的同源策略限制,导致本地服务访问其他地址时,无法获取相应的数据,即为跨域
同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
当前页面url | 被请求页面url | 是否跨域 | 原因 |
---|---|---|---|
www.test.com/ | www.test.com/index.html | 否 | 同源(协议、域名、端口号相同) |
www.test.com/ | www.test.com/index.html | 跨域 | 协议不同(http/https) |
www.test.com/ | www.baidu.com/ | 跨域 | 主域名不同(test/baidu) |
www.test.com/ | blog.test.com/ | 跨域 | 子域名不同(www/blog) |
www.test.com:8080/ | www.test.com:7001/ | 跨域 | 端口号不同(8080/7001) |
3. 解决方案
丑话说在前头:该解决方案仅用于解决开发阶段拿不到数据的问题,上线后还是会遇到,所以根源还是得后端服务器对于CORS的支持,需要后端进行配置
3.1 axios请求与proxy代理配置
- 原理:浏览器通过webpack本地代理请求远程服务器
sequenceDiagram
本地服务器->>webpack代理服务器: 发送请求
webpack代理服务器->>目标服务器: 转发本地服务器请求
目标服务器-->>webpack代理服务器: 获取数据
webpack代理服务器-)本地服务器: 拿到数据
-
proxy代理配置
目标文件:vue.config.js
//vue.config.js文件配置 const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, lintOnSave: false, publicPath: './', devServer: { host: 'localhost', //自己的ip地址 // https: true, port: 6103, //自己服务器的端口号 // client: { // webSocketURL: 'ws://0.0.0.0:6103/ws', // }, headers: { 'Access-Control-Allow-Origin': '*', }, proxy: { // '/interface' 可以理解为 请求目标地址的标识符,也可以使用其他命名代替 '/interface': { target:'http://60.15.96.130:8092/interface', changeOrigin: true, //是否跨域 ws: true, //是否代理 websockets secure: true, //是否https接口 pathRewrite: { '^/interface': ''//这里理解成用‘/interface’代替target里面的地址,后面组件中我们掉接口时直接用api代替 比如我要调用'http://40.00.100.100:3002/user/add',直接写‘/interface/user/add’即可 } } } }, })
-
使用案例
// 创建 供热 实例对象 import axios from 'axios'; export const heatingService = axios.create({ baseURL: "/interface", //此处将通过webpack进行代理 timeout: 30000, // 设置请求超时时间设置为30秒 responseType: 'json', withCredentials: true, // 是否允许带cookie这些 }); getPrimaryPipeNet() { return heatingService({ url: "getPrimaryPipeNet", method: 'get', }) } async getHeadingPipe() { const data = await heatingApi.getPrimaryPipeNet(); console.log("数据", data); },