记一次vue跨域的解决


Posted in Javascript onOctober 21, 2020

好久不见,今天想写的是前段时间碰到的一个小问题。其实故事背景是前端的同学跟我说他们前端请求不了我后端的数据,说是跨域了。

其实跨域的问题,在如今前后端的时代非常常见,如果图方便的话,一般是在后端的请求以及拦截器中设置header,但是有一些业务需求单纯后端是解决不了的。还是需要前端自行来处理,这次碰到的就是前端需要自行处理的情况。

这里我不细说跨域的解决方案,只聊聊我是怎么解决的。如果大家想要知道更详细的跨域知识,可以点个在看!我下次写一个专题。

vue跨域代理解决方案

记一次vue跨域的解决

其实需求比较简单,就是先post模拟登陆到B服务器,然后get请求B服务器上指定接口的数据,返回给A服务器。

当然这里的A服务器目前是处于我本机电脑。

首先,我们需要在根目录下配置vue.config.js,这个文件不是每个项目都有的,如果没有的可以自行配置。根据vue官网的说法,这个文件是可选配置,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。

这个文件里面具体配置有什么,这里给大家官网的地址:

https://cli.vuejs.org/zh/config

官网中详细介绍了每一个参数的配置,当然我们需要什么就可以拿什么参数来配置。这里我从网上找了一份比较全面的vue.config.js,大家直接复制粘贴即可

// vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部分,具体配置参考文档
module.exports = {
// 部署生产环境和开发环境下的URL。
// 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
//例如 https://www.my-app.com/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.my-app.com/my-app/,则设置 baseUrl 为 /my-app/。
//baseUrl 从 Vue CLI 3.3 起已弃用,请使用publicPath
//baseUrl: process.env.NODE_ENV === "production" ? "./" : "/",
publicPath: process.env.NODE_ENV === "production" ? "./" : "/",

// outputDir: 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)
outputDir: "mycli3",
//用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
assetsDir: "assets",
//指定生成的 index.html 的输出路径 (打包之后,改变系统默认的index.html的文件名)
// indexPath: "myIndex.html",
//默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存。你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变)
filenameHashing: false,

//  lintOnSave:{ type:Boolean default:true } 问你是否使用eslint
lintOnSave: true,
//如果你想要在生产构建时禁用 eslint-loader,你可以用如下配置
// lintOnSave: process.env.NODE_ENV !== 'production',

//是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了,但是这会让你的应用额外增加 10kb 左右。(默认false)
// runtimeCompiler: false,

/**
 * 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
 * 打包之后发现map文件过大,项目文件体积很大,设置为false就可以不输出map文件
 * map文件的作用在于:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。
 * 有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错。
 * */
productionSourceMap: false,

// 它支持webPack-dev-server的所有选项
devServer: {
  host: "localhost",
  port: 8081, // 端口号
  https: false, // https:{type:Boolean}
  open: true, //配置自动启动浏览器
  // 配置多个代理
  proxy: {
    "/apis": {
      target: "http://xxx.xx.xx.xx:xxxxx",// 要访问的接口域名
      ws: true,// 是否启用websockets
      changeOrigin: true, //开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
      pathRewrite: {
        '^/apis': '' //这里理解成用'/api'代替target里面的地址,比如我要调用'http://40.00.100.100:3002/user/add',直接写'/api/user/add'即可
      }
    }
  }
}
};

当然,我们可能不需要这么多的配置,这里我们主要来看这段代码:

devServer: {
   host: "localhost",
   port: 8081, // 端口号
   https: false, // https:{type:Boolean}
   open: true, //配置自动启动浏览器
   // 配置多个代理
   proxy: {
     "/apis": {
       target: "http://xxx.xx.xx.xx:xxxxx",// 要访问的接口域名
       ws: true,// 是否启用websockets
       changeOrigin: true, //开启跨域
       pathRewrite: {
         '^/apis': '' //这里理解成用'/api'代替target里面的地址,比如我要调用'http://40.00.100.100:3002/user/add',直接写'/api/user/add'即可
       }
     }

这个地方就是配置代理的地方,如果你是使用webpack模板来构建的vue项目,这个配置文件是config/index.js,其实功能类似。

在proxy字段中target就是我们要跨域的url,pathRewrite中的^/apis,就是来替代target中你所填写的url,什么意思呢?可以继续看下面。

this.$axios({
  method: "POST",
  url: `/apis/login`,
  headers: {
   'Content-Type': 'application/x-www-form-urlencoded'
  },

  data: {
       "email": "xxxxxxx",
       "password": "xxxxxxx",
       "remember": "on"
      },
  withCredentials: true,

 })

在上面的url中你看到我写的是/apis/login,但是实际上请求的是http://xxx.xx.xx.xx:xxxxx/login。也就是说apis将target中的url代替了,这样就能够让vue知道你这里需要用到代理的方式。

其实到了这里跨域的问题已经解决了,你再次请求的时候会发现没有报跨域的错误。

但是,又会有一些新的错误,可能你不会遇到但很有可能也会遇到,这个跟后端接受数据的格式有关。

将axios中的表单数据转为form-data形式

如果你不是form-data的形式,你可能会遇到400的错误,400错误按照网上的说法是你的content-type没设置对,但这只是一方面,另一方面是你所传递的data不一定跟后端相契合。

这里你可能需要通过axios设置拦截器来解决这个问题:

在你的main.js中,设置如下:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './api'
import axios from 'axios'
import qs from 'qs'


Vue.config.productionTip = false
Vue.prototype.$axios = axios

axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
axios.defaults.headers.post["Access-Control-Allow-Origin"] = "*";
// 设置拦截器
axios.interceptors.request.use(
  config => {
   if (config.method === 'post') {
    config.data = qs.stringify(config.data);
   }
   return config;
  },
  error =>{
   return Promise.reject(error);
  }
);

new Vue({
 router,
 store,
 render: h => h(App)
}).$mount('#app')

总结

这篇文章对于跨域写得并不是很全面,但是对于这方面有困惑的同学,我相信看了之后会茅塞顿开。跨域问题的思考思路无非就是前端和后端两方面。分别简单测试一下就能够锁定问题出在哪方面。如果你觉得这篇文章对你现在或者以后有用,麻烦给个在看支持吧!

以上就是记一次vue跨域的解决的详细内容,更多关于vue 跨域的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
初学JavaScript_03(ExtJs Grid的简单使用)
Oct 02 Javascript
JQuery 学习笔记 选择器之二
Jul 23 Javascript
JavaScript 格式字符串的应用
Mar 29 Javascript
jQuery阻止冒泡和HTML默认操作
Nov 17 Javascript
ParseInt函数参数设置介绍
Jan 02 Javascript
JavaScript实现两个Table固定表头根据页面大小自行调整
Jan 03 Javascript
跟我学习javascript的异步脚本加载
Nov 20 Javascript
jQuery插件zTree实现获取一级节点数据的方法
Mar 08 Javascript
input框中自动展示当前日期yyyy/mm/dd的实现方法
Jul 06 Javascript
Vue中div contenteditable 的光标定位方法
Aug 25 Javascript
vue1.0和vue2.0的watch监听事件写法详解
Sep 11 Javascript
JavaScript实现鼠标经过表格某行时此行变色
Nov 20 Javascript
解决Vue项目中tff报错的问题
Oct 21 #Javascript
vue-cli3自动消除console.log()的调试信息方式
Oct 21 #Javascript
js 压缩图片的示例(只缩小体积,不更改图片尺寸)
Oct 21 #Javascript
vue-cli4使用全局less文件中的变量配置操作
Oct 21 #Javascript
Vue全局使用less样式,组件使用全局样式文件中定义的变量操作
Oct 21 #Javascript
js 图片懒加载的实现
Oct 21 #Javascript
uniapp实现可以左右滑动导航栏
Oct 21 #Javascript
You might like
Mysql的GROUP_CONCAT()函数使用方法
2008/03/28 PHP
mysql From_unixtime及UNIX_TIMESTAMP及DATE_FORMAT日期函数
2010/03/21 PHP
通过5个php实例细致说明传值与传引用的区别
2012/08/08 PHP
nginx+php-fpm配置文件的组织结构介绍
2012/11/07 PHP
$_GET['goods_id']+0 的使用详解
2013/06/06 PHP
PHP实现将科学计数法转换为原始数字字符串的方法
2014/12/16 PHP
PHP 实现公历日期与农历日期的互转换
2017/09/13 PHP
关于PHP5.6+版本“No input file specified”问题的解决
2019/12/11 PHP
js模拟实现Array的sort方法
2007/12/11 Javascript
优化javascript的执行速度
2010/01/23 Javascript
在Ajax中使用Flash实现跨域数据读取的实现方法
2010/12/02 Javascript
js获得网页背景色和字体色的方法
2014/03/21 Javascript
node.js程序作为服务并在windows下开机自启动(用forever)
2017/03/29 Javascript
详解从angular-cli:1.0.0-beta.28.3升级到@angular/cli:1.0.0
2017/05/22 Javascript
jQuery异步提交表单实例
2017/05/30 jQuery
浅谈angularJS的$watch失效问题的解决方案
2017/08/11 Javascript
在vue中添加Echarts图表的基本使用教程
2017/11/22 Javascript
Vue中的slot使用插槽分发内容的方法
2018/03/01 Javascript
javascript实现文件拖拽事件
2018/03/29 Javascript
Vue中的混入的使用(vue mixins)
2018/06/01 Javascript
小程序:授权、登录、session_key、unionId的详解
2019/05/15 Javascript
vue中路由跳转不计入history的操作
2020/09/21 Javascript
python基础知识小结之集合
2015/11/25 Python
pyspark 读取csv文件创建DataFrame的两种方法
2018/06/07 Python
python3+PyQt5 实现Rich文本的行编辑方法
2019/06/17 Python
如何解决flask修改静态资源后缓存文件不能及时更改问题
2020/08/02 Python
详解css3自定义滚动条样式写法
2017/12/25 HTML / CSS
html5 canvas 使用示例
2010/10/22 HTML / CSS
英国户外服装品牌:Craghoppers
2019/04/25 全球购物
新员工入职感言
2014/02/01 职场文书
优秀本科毕业生自荐信
2014/07/04 职场文书
好人好事演讲稿
2014/09/01 职场文书
政风行风自查自纠报告
2014/10/21 职场文书
2015年学校安全工作总结
2015/04/22 职场文书
2015年重阳节活动主持词
2015/07/30 职场文书
《围炉夜话》110句人生箴言,精辟有内涵,引人深思
2019/10/23 职场文书