Loading

vue-cli3开发解决axios跨域问题

技术概述

本篇博客主要介绍使用vue-cli3开发时axios跨域问题的解决方法。这个问题是我们小组在进行后台开发涉及到交互部分时遇到的一个大坑,网上虽然有很多的教程,但是有的地方的描述并不是特别的详细,尤其是url部分的写法。所以特地写一篇博客来梳理一下解决流程。希望可以帮助到大家。

技术详述

此处默认已经搭建好了vue-cli框架。

步骤一:安装axios。

  • 方法一:使用vue ui命令进入可视化界面安装axios。
    @vue/cli3.0增加一个可视化项目管理工具,全局安装完成cli3.0之后,可以直接在cmd输入命令:vue ui 启动即可,地址默认是localhost:8000
    如下图:
    image
    接下来点击安装依赖搜索axios来安装axios。
    image
    image
  • 方法二:使用npm命令npm install axios --save安装axios。如下图:
    image

步骤二: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) //查询失败返回的值
	 });

你以为的流程:

image

遇到问题

  • 问题一:使用相对路径写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);
		  //省略具体内容
        });

image

  • 问题二:直接使用后端服务器上的接口url。eg:http://47.106.241.182:8082/admin/login这导致跨域问题。(虽然使用前端解决了这个问题,但因为在后期后端也使用Spring boot解决了这个问题所以暂时无法复现)
    网上偷了张图代替:
    image

补充说明:
跨域:指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);
		  //省略具体内容
        });

当我们再次请求就不会显示跨域了。
image

实际的流程:

image

总结

解决axios跨域问题其实并不难,只是我曾经在这上面踩了许许多多的坑。比如:配置了代理,但是在axios请求的时候并没有写/api,又或者pathRewrite中自以为的写成'^/api':'/'等等,导致一直没有解决。知道各种尝试解决的那一刻才恍然大悟。希望这篇博客可以对大家有所帮助。
ps:当然也可以让后端来解决hhh但是前端解决也不麻烦啦。

参考博客

axios解决跨域问题(vue-cli3.0) 作者:累成一条狗
axios处理跨域问题 作者:liutianou
axios请求中跨域及post请求问题解决方案 作者:瑾小瑜

posted @ 2021-06-28 19:48  王大鱼Yu  阅读(1263)  评论(0编辑  收藏  举报