记一次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 相关文章推荐
jQuery timers计时器简单应用说明
Oct 28 Javascript
jquery slibings选取同级其他元素的实现代码
Nov 15 Javascript
jQuery循环动画与获取组件尺寸的方法
Feb 02 Javascript
QQ登录背景闪动效果附效果演示源码下载
Sep 22 Javascript
vue学习笔记之vue1.0和vue2.0的区别介绍
May 17 Javascript
详解vue slot插槽的使用方法
Jun 13 Javascript
bootstrap table服务端实现分页效果
Aug 10 Javascript
web前端vue实现插值文本和输出原始html
Jan 19 Javascript
vue中使用heatmapjs的示例代码(结合百度地图)
Sep 05 Javascript
详解微信小程序之提高应用速度小技巧
Jan 07 Javascript
jquery实现的放大镜效果示例
Feb 24 jQuery
Vue移动端用淘宝弹性布局lib-flexible插件做适配的方法
May 26 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
一些常用的php简单命令代码集锦
2007/09/24 PHP
php 函数中使用static的说明
2012/06/01 PHP
PHP解析RSS的方法
2015/03/05 PHP
PHP缓存工具XCache安装与使用方法详解
2018/04/09 PHP
PHP排序二叉树基本功能实现方法示例
2018/05/26 PHP
PHP JWT初识及其简单示例
2018/10/10 PHP
laravel 时间格式转时间戳的例子
2019/10/11 PHP
设定php简写功能的方法
2019/11/28 PHP
javascript操纵OGNL标签示例代码
2014/06/16 Javascript
javascript检测是否联网的实现代码
2014/09/28 Javascript
IE中document.createElement的iframe无法设置属性name的解决方法
2015/09/14 Javascript
JS判断当前页面是否在微信浏览器打开的方法
2015/12/08 Javascript
AngularJS 使用ng-repeat报错 [ngRepeat:dupes]
2017/01/19 Javascript
微信小程序中时间戳和日期的相互转换问题
2018/07/09 Javascript
@angular前端项目代码优化之构建Api Tree的方法
2018/12/24 Javascript
微信小程序向Java后台传输参数的方法实现
2020/12/10 Javascript
Node.js 中如何收集和解析命令行参数
2021/01/08 Javascript
跟老齐学Python之传说中的函数编写条规
2014/10/11 Python
python开发之IDEL(Python GUI)的使用方法图文详解
2015/11/12 Python
Python3学习笔记之列表方法示例详解
2017/10/06 Python
Django中使用Celery的教程详解
2018/08/24 Python
解决python Markdown模块乱码的问题
2019/02/14 Python
PyQt5实现从主窗口打开子窗口的方法
2019/06/19 Python
Python图像处理库PIL的ImageFilter模块使用介绍
2020/02/26 Python
Python批量将图片灰度化的实现代码
2020/04/11 Python
python中怎么表示空值
2020/06/19 Python
keras K.function获取某层的输出操作
2020/06/29 Python
OpenCV4.1.0+VS2017环境配置的方法步骤
2020/07/09 Python
python 实现图片批量压缩的示例
2020/12/18 Python
Melissa香港官网:MDreams
2016/07/01 全球购物
什么是SQL Server的确定性函数和不确定性函数
2016/08/04 面试题
可以使用抽象函数重写基类中的虚函数吗
2013/06/02 面试题
酒店保洁主管岗位职责
2013/11/28 职场文书
入党积极分子介绍信
2014/01/17 职场文书
旅游局领导班子“四风”问题对照检查材料思想汇报
2014/09/29 职场文书
介绍信的格式
2015/01/30 职场文书