技术概述
本篇博客主要介绍使用vue-cli3开发时axios跨域问题的解决方法。这个问题是我们小组在进行后台开发涉及到交互部分时遇到的一个大坑,网上虽然有很多的教程,但是有的地方的描述并不是特别的详细,尤其是url部分的写法。所以特地写一篇博客来梳理一下解决流程。希望可以帮助到大家。
技术详述
此处默认已经搭建好了vue-cli框架。
步骤一:安装axios。
- 方法一:使用vue ui命令进入可视化界面安装axios。
@vue/cli3.0增加一个可视化项目管理工具,全局安装完成cli3.0之后,可以直接在cmd输入命令:vue ui 启动即可,地址默认是localhost:8000
如下图:
接下来点击安装依赖
搜索axios
来安装axios。
- 方法二:使用npm命令
npm install axios --save
安装axios。如下图:
步骤二:main.js中引入axios
import axios from 'axios' //引入 axios
Vue.prototype.$axios = axios //把axios挂载到vue的原型中,在vue中每个组件都可以使用axios发送请求
步骤三:在要使用axios请求的页面引入axios
import axios from "axios";
步骤四:书写axios请求(以get请求为例)
axios.get('http://xxx.xx.xxx/xxx/xxx',{
params:{
xxx = xxx
}
})
.then(res => {
console.log(res) //查询成功返回的值
}).catch(error => {
console.log(error) //查询失败返回的值
});
你以为的流程:
遇到问题
- 问题一:使用相对路径写axios请求。此时会发现请求的url中ip和端口号为前台的ip和端口号。并不是实际上的接口url,所以报错404。
this.$axios.post(
"/admin/login",
qs.stringify({
account: this.account,
password: this.password,
}),
{
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
}).then((res) => {
console.log(res.data);
//省略具体内容
});
- 问题二:直接使用后端服务器上的接口url。eg:
http://47.106.241.182:8082/admin/login
这导致跨域问题。(虽然使用前端解决了这个问题,但因为在后期后端也使用Spring boot解决了这个问题所以暂时无法复现)
网上偷了张图代替:
补充说明:
跨域:指ip、端口、协议三者有任意不同则会跨域。
像我们请求的时候本地是http://172.20.84.235:8080/
,后端接口的url是http://47.106.241.182:8082/xxx
,此时ip和端口号不同,则产生了跨域。
解决方法
在
vue.config.js
中设置代理。vue-cli3可能没有这个文件,那么新建一个就好。配置如下:
module.exports = {
/* 部署生产环境和开发环境下的URL:可对当前环境进行区分,baseUrl 从 Vue CLI 3.3 起已弃用,要使用publicPath */
publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
/* 输出文件目录:在npm run build时,生成文件的目录名称 */
outputDir: 'dist',
/* 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录 */
assetsDir: "assets",
/* 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度 */
productionSourceMap: false,
/* 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变) */
filenameHashing: false,
/* 代码保存时进行eslint检测 */
lintOnSave: true,
/* webpack-dev-server 相关配置 */
devServer: {
/* 自动打开浏览器 */
open: false,
port: 8080, //本地端口号
https: false,
hotOnly: false,
/* 使用代理 */
proxy: {
'/api': {
target: 'http://47.106.241.182:8082',//服务器协议、ip和端口号
secure: false, // 如果是https接口,需要配置这个参数
ws: true,//是否代理websockets
changeOrigin: true,
pathRewrite:{
'^/api':''
}
}
},
}
}
重点在于proxy。
-
/api:请求的url使用
/api
开始时,才会调用代理。eg:请求url为/api/admin/login
实际对应的请求地址为http://47.106.241.182:8082/api/admin/login
。 - 但我们的请求的接口url可能并不含/api。所以就需要使用
pathRewrite:{ '^/api':'' }
来将url中的/api替换为空。得到正确的请求urlhttp://47.106.241.182:8082/admin/login
- 如果你的请求的所有的url恰好都含有/api,那么可以选择不写
pathRewrite
或者写成pathRewrite:{ '^/api':'/api' }
配置完成后,我们将上面的axios请求改正如下。
this.$axios.post(
"/api/admin/login",//这个地方变了!!!
qs.stringify({
account: this.account,
password: this.password,
}),
{
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
}).then((res) => {
console.log(res.data);
//省略具体内容
});
当我们再次请求就不会显示跨域了。
实际的流程:
总结
解决axios跨域问题其实并不难,只是我曾经在这上面踩了许许多多的坑。比如:配置了代理,但是在axios请求的时候并没有写/api,又或者pathRewrite中自以为的写成'^/api':'/'等等,导致一直没有解决。知道各种尝试解决的那一刻才恍然大悟。希望这篇博客可以对大家有所帮助。
ps:当然也可以让后端来解决hhh但是前端解决也不麻烦啦。
参考博客
axios解决跨域问题(vue-cli3.0) 作者:累成一条狗
axios处理跨域问题 作者:liutianou
axios请求中跨域及post请求问题解决方案 作者:瑾小瑜