此时你就可以通过proxyTable来解决跨域问题,规范也支持得并不全

  • 栏目:前端 时间:2020-01-04 13:03
<返回列表
target:"",//访问的服务器地址changeOrigin:true,//true为开启代理pathRewrite:{ '^/user': '/'//路径的替换规则}

前言

对于前端开发人员来讲,当你在开发环境中与后台开发人员进行数据联调时,总会遇到烦人的跨域问题!

changeOrigin的属性值为一个布尔值,如果设置为true,那么本地会虚拟一个NODE服务端接收你的请求并代你发送该请求(中间件)。[本质上是本地开了一个服务器dev-server,所有的请求都通过这里转发出去。]

vue - 2.5.11 vue-cli 使用模板 webpack-simple http请求:axios

解决跨域的方法有很多种,比如你和后台人员经过友好协商后,你可以通过JSONP的方式或者让后台人员将代码设置为允许你进行跨域!但是往往前后台开发人员的配合默契度是不太高的。如果后台只给你接口,并明确告诉你不允许修改接口,怎么办?怎么办才能实现跨域?此时你就可以通过proxyTable来解决跨域问题!通过proxyTable解决跨域在Vue-cli当中是很简单的。只需修改config文件夹下的index.js中的proxyTable就能实现:

因为服务端语言是没有跨域问题的,所以这样最终就解决了跨域问题了。不过这只适用于开发环境,上线后可以使用反向代理nginx。

Vue 官方对于 ie 浏览器版本兼容情况的描述是 ie9+,即是 ie9 及更高的版本。经过测试,Vue 的核心框架 vuejs 本身,以及生态的官方核心插件均可以在 ie9 上正常使用。

//代理配置表,在这里可以配置特定的请求代理到对应的API接口proxyTable:{ "/api":{ target:"http://www.zhangpeiyue.com",//访问的服务器地址 changeOrigin:true,//true为开启代理 //secure: true, // 如果是https接口,需要配置这个参数 pathRewrite:{ '^/api': '/'//路径的替换规则 /* *这里的配置是正则表达式,以/api开头的路径将会被‘/'替换掉 *假如后台文档的接口是 "http://www.zhangpeiyue.com/user/add" *前端调取API接口应写:axios.get('/api/user/add') */ } }}

解释为啥开发环境这种 proxy代理不可以:这种配置本身在devServer配置,基于node环境,所以只适合本地开发使用。在生产环境在,前端项目部署在Apache中 不具备这种条件,官方也不支持这种做法。

Vue 的作者尤雨溪对于Vue 的学习建议 中有提及为了将项目更好的生态化/工程化,要尽可能学习及使用新的 ECMAScript 规范。目前 ES6/ES2015 是可用度和稳定度较高的规范,文档齐全,国内还有 阮一峰 《ECMAScript 6 入门》 做了大量的文档翻译,开发环境可谓完善。然而版本较旧的浏览器并不支持 es6 规范,尤其是 ie 浏览器,即使是最高的 ie11 版本,对于 es6 规范也支持得并不全。如此则需要对所有原生不支持 ES6 特性的浏览器做兼容性处理。

以上代码的“/api"你可以认为用于代替target里面的地址,调取接口的地址直接用api来替换。比如后台接口地址为:"

生产环境使用Nginx反向代理或者搭配后端使用CORS进行跨域

本文将针对使用 Vue 生态开发完成的网站,以 ie9 版本为基础兼容目标,实现全功能正常使用的全面兼容解决方案。

//代理配置表,在这里可以配置特定的请求代理到对应的API接口proxyTable:{ "/adv":{ target:"http://adv.zhangpeiyue.com",//访问的服务器地址 changeOrigin:true,//true为开启代理 pathRewrite:{ '^/adv': '/'//路径的替换规则 } }, "/user":{ target:"http://user.zhangpeiyue.com",//访问的服务器地址 changeOrigin:true,//true为开启代理 pathRewrite:{ '^/user': '/'//路径的替换规则 } }}

ES6兼容

以上代码"/adv"与"/user"分别负责项目中的广告模块与用户模块。例如:后台文档的地址是:“')

在 ie9 的环境上,es6 的部分新对象、表达式,并不支持,解决方案是使用babel-polyfill组件,它可以将 es6 的代码翻译成低版本浏览器可以识别的 es5 代码

注意:

配置修改完以后一定要重新npm run dev 一次

npm i babel-polyfill --save-dev
补充:

changeOrigin的属性值为一个布尔值,如果设置为true,那么本地会虚拟一个NODE服务端接收你的请求并代你发送该请求。因为服务端语言是没有跨域问题的,所以这样最终就解决了跨域问题了。不过这只适用于开发环境,上线后可以使用反向代理nginx。

图片 1

安装完成后,在项目的主入口文件 main.js 的首行就可以直接引用

import 'babel-polyfill';

在项目使用 vue-cli 生成的代码中,根目录有一个 .babelrc 文件,这是项目使用 babel 的配置文件。在默认生成的模板内容中,增加 "useBuiltIns": "entry"的设置内容,这是一个指定哪些内容需要被 polyfill 的设置

useBuiltIns 有三个设置选项

false - 不做任何操作 entry - 根据浏览器版本的支持,将 polyfill 需求拆分引入,仅引入有浏览器不支持的polyfill usage - 检测代码中ES6/7/8 等的使用情况,仅仅加载代码中用到的 polyfill

这里推荐设置为entry,完整的.babelrc内容如下:

{ "presets": [ [ "env", { "modules": false, "useBuiltIns": "entry" } ], "stage-3" ]}

加入这些代码后,工程里的大部分内容已可兼容到 ie9 版本

Number对象

即使在使用babel-polyfill做代码翻译后,发现还是有一些 es6 的新特性并没有解决,比如说 Number 对象的parseIntparseFloat方法

es6 将全局方法parseInt()parseFloat(),移植到 Number对象上面,行为完全保持不变。这样做的目的,是逐步减少全局性方法,使得语言逐步模块化。

解决这个问题不需要引入包来解决,同样在项目主入口文件 main.js 加入以下代码(代码尽可能靠前,最好是在引用babel-polyfill之后 )

if (Number.parseInt === undefined) Number.parseInt = window.parseInt;if (Number.parseFloat === undefined) Number.parseFloat = window.parseFloat;

requestAnimationFrame方法

window.requestAnimationFrame 是浏览器用于定时循环操作的一个接口,类似于 setTimeout,主要用途是按帧对网页进行重绘。

requestAnimationFrame的优势,在于充分利用显示器的刷新机制,比较节省系统资源。显示器有固定的刷新频率,也就是说,每秒最多只能重绘60次或75次,requestAnimationFrame 的基本思想就是与这个刷新频率保持同步,利用这个刷新频率进行页面重绘。此外,使用这个API,一旦页面不处于浏览器的当前标签,就会自动停止刷新。这就节省了CPU、GPU和电力。

不过有一点需要注意,requestAnimationFrame 是在主线程上完成。这意味着,如果主线程非常繁忙,requestAnimationFrame的动画效果会大打折扣。

window.requestAnimationFrame()方法告诉浏览器您希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。

有部分第三方组件就使用了这个方法,例如部分文件上传、图片处理类的组件;那么在这类型的组件在 ie9 下使用时,会报出

SCRIPT5007: Expected object.

window.requestAnimationFrame()的最低兼容 ie 版本为 10,那么在 ie9 上做兼容就需要制作 requestAnimationFrame polyfill

 { var lastTime = 0; var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function { var currTime = new Date; var timeToCall = Math.max(0, 16 - ; var id = window.setTimeout { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function { clearTimeout;

Gist:requestAnimationFrame polyfill

这部分代码同样是尽可能在网站入口处就执行

http网络请求

在大多数的 Web 项目中,网站的页面和服务在同一个工程进行开发和部署,在大前端的新型模式下,我们建议尽可能对网站的前端和后端进行完全分离,前后端分离的好处和意义这里不再赘述。

既然是前后端分离,那么部署也必然是各自独立部署,不同的访问路径,就会产生跨域访问的问题

服务端已完整开启 CROS 跨域支持 http 组件使用 axios axios 设置 withCredentials 为 true 开启跨域访问时携带 cookie 数据

高版本浏览器仅需要完成背景情况中的功能,即可支持跨域数据请求功能

axios 进行数据请求时,默认使用 XMLHttpRequest 对象,在检测到当前请求是跨域访问时,axios 会测试浏览器是否支持 XDomainRequest 对象,若支持则优先使用。

ie8 / ie9 的 XMLHttpRequest 对象,不支持跨域访问,该对象在 ie10 后才原生支持跨域访问。微软的解决方案是在 ie8 / ie9 中提供了XDomainRequest 对象来进行解决跨域问题,虽然使用该对象可以跨域访问成功,并返回数据,但它却依然是一个功能不完整的半成品,它的使用有诸多限制:

XDR 仅支持 GET 与 POST 两种请求方式 XDR 不支持自定义的请求头,若服务端使用 header 的自定义参数进行做身份验证,则不可用 请求头的 Content-Type 只允许设置为 text/plain XDR 不允许跨协议的请求,如果网页在 HTTP 协议下,就只能请求 HTTP 协议下的接口,不能访问 HTTPS 接口 XDR 只接受HTTP/HTTPS 的请求 发起请求的时候,不会携带 authentication 或 cookies

微软虽然提供了解决方案,但却是不折不扣的鸡肋,根本无法胜任系统中各种场景的数据请求需求,至此,axios 对 ie9 的跨域数据请求已无能为力。

完美解决方案:代理

虽然 axios 对 ie9 跨域已无能为力,但前端项目打包的解决方案 webpack 提供了一个优雅而彻底解决问题的方式:代理

devServer.proxy

webpack 的 devServer.proxy的功能是由http-proxy-middleware 项目来实现的

实现原理是将目标位置的请求代理为前端服务本地的请求,既然是代理成为本地的请求,就不存在跨域的问题,axios 就会用回 XMLHttpRequest对象进行数据请求,一切都恢复正常了,header、cookies、content-type、authentication 等内容都被正确传递到服务端。

项目中 webpack.config.js 的配置

devServer: { historyApiFallback: true, noInfo: true, overlay: true, proxy: { '/api': { target: 'http://localhost:8081/myserver', pathRewrite: { '^/api': '' } } }}

配置中指定了将 服务的位置代理为本地前端服务的

即是 /api 的前缀代表了服务端,所以在使用 axios 时,需要对每个服务端请求都增加上 /api 的前缀;通常在项目开发中,需要对数据请求组件 axios 进行二次封装,以达到统一设置默认参数,统一数据请求入口等目的,那么此时就只需要在二次封装的文件里统一调整请求前缀即可。

不过,webpack 的devServer.proxy仅在开发模式下可用,生产模式下无法使用。开发模式下,调试服务可以读取 webpack.config.js 中的配置内容进行实时代理,而项目在部署到生产环境前,需要将工程进行编译转换成静态的 js 文件,没有调试服务的支撑自然是无法进行请求代理的。

nginx 配置

虽然 devServer.proxy 的功能仅能工作于开发模式,那么在生产模式下,自然也是有解决方案的;通常 Vue 的项目在编译成最终的 js 文件后,仅需要静态服务器即可,这其中又以 nginx 为最优选择方案,轻量、高性能、高并发、反向代理服务等均为其优点,这里需要做的数据请求代理的功能就使用到了 nginx 的 反向代理 功能

conf/nginx.conf 文件配置增加以下内容

location /api/ { proxy_pass http://localhost:8081/myserver/;}

该配置同样是将 的目标服务端位置代理为本地服务的 /api 路径,如此,生产环境下的数据请求问题也得以解决

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

上一篇:没有了 下一篇:没有了

更多阅读

此时你就可以通过proxyTable来解决跨域问题

前端 2020-01-04
target:"",//访问的服务器地址changeOrigin:true,//true为开启代理pathRewrite:{ '^/user': '/'//路径的替换规则...
查看全文

SPA应用的核心在于使用无刷新的方式更改

前端 2020-01-04
问题: 本文介绍如何使用backbone的history模块实现SPA应用里面的URL管理。SPA应用的核心在于使用...
查看全文

韦德体育兼顾浏览器的通用方法,在什么

前端 2020-01-04
1.浮动元素有什么特征?对父容器、其他浮动元素、普通元素、文字分别有什么影响? ** 特征...
查看全文

友情链接: 网站地图

Copyright © 2015-2019 http://www.koi-bumi.com. 韦德体育有限公司 版权所有