记一次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 DOM 学习第三章 内容表格
Feb 19 Javascript
Iframe实现跨浏览器自适应高度解决方法
Sep 02 Javascript
BootStrap下jQuery自动完成的样式调整
May 30 Javascript
Document.body.scrollTop的值总为零的快速解决办法
Jun 09 Javascript
JS实现复制内容到剪贴板功能兼容所有浏览器(推荐)
Jun 17 Javascript
js使用Replace结合正则替换重复出现的字符串功能示例
Dec 27 Javascript
Vue2几种常见开局方式详解
Sep 09 Javascript
微信小程序列表中item左滑删除功能
Nov 07 Javascript
JavaScript模板引擎应用场景及实现原理详解
Dec 14 Javascript
实用的Vue开发技巧
May 30 Javascript
《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析
Apr 07 Javascript
JavaScript实现像雪花一样的Hexaflake分形
Jul 07 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
如何过滤高亮显示非法字符
2006/10/09 PHP
虚拟主机中对PHP的特殊设置
2006/10/09 PHP
phpmailer发送gmail邮件实例详解
2013/06/24 PHP
php生成缩略图示例代码分享(使用gd库实现)
2014/01/20 PHP
PHP类的反射用法实例
2014/11/03 PHP
Yii多表联合查询操作详解
2016/06/02 PHP
Yii针对添加行的增删改查操作示例
2016/10/18 PHP
php的常量和变量实例详解
2017/06/27 PHP
PHP Swoole异步读取、写入文件操作示例
2019/10/24 PHP
javascript 多种搜索引擎集成的页面实现代码
2010/01/02 Javascript
关于IE BUG与字符串截取substr的解决办法
2013/04/10 Javascript
js 弹出新页面避免被浏览器、ad拦截的一种新方法
2014/04/30 Javascript
jQuery 移动端artEditor富文本编辑器
2016/01/11 Javascript
JS把内容动态插入到DIV的实现方法
2016/07/19 Javascript
js时间控件只显示年月
2017/01/08 Javascript
JavaScript全屏和退出全屏事件总结(附代码)
2017/08/17 Javascript
浅谈Angular文字折叠展开组件的原理分析
2017/11/24 Javascript
Vue实现数据请求拦截
2019/10/23 Javascript
vue实现多个echarts根据屏幕大小变化而变化实例
2020/07/19 Javascript
[01:09:40]Newbee vs Pain 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python转码问题的解决方法
2008/10/07 Python
Python中的自定义函数学习笔记
2014/09/23 Python
Python 26进制计算实现方法
2015/05/28 Python
python在控制台输出进度条的方法
2015/06/20 Python
Python实现LRU算法的2种方法
2015/06/24 Python
对python创建及引用动态变量名的示例讲解
2018/11/10 Python
python tkinter窗口最大化的实现
2019/07/15 Python
python使用opencv实现马赛克效果示例
2019/09/28 Python
pytorch 实现cross entropy损失函数计算方式
2020/01/02 Python
python zip,lambda,map函数代码实例
2020/04/04 Python
如何使用python socket模块实现简单的文件下载
2020/09/04 Python
viagogo意大利票务平台:演唱会、体育比赛、戏剧门票
2018/01/26 全球购物
应聘教师自荐信
2013/10/12 职场文书
银行职业规划书范文
2013/12/28 职场文书
部队2014年终工作总结
2014/11/27 职场文书
寒假生活随笔
2015/08/15 职场文书