前言背景vue-2.5.11vue-cli使用模板webpack-simplehttp请求:axiosVue官方说明对ie浏览器版本兼容为ie9+,即ie9及以后版本。经测试,Vue的核心框架,vuejs本身,以及生态官方的核心插件(VueRouter,Vuex等)都可以在ie9上正常使用。Vue的作者游玉玺在对Vue的学习建议中提到,为了让项目更加生态化/工程化,需要尽可能地学习和使用新的ECMAScript规范。目前ES6/ES2015是高可用和稳定的规范,文档也很齐全。在国内,阮一峰《ECMAScript 6 入门》做了很多文档翻译,开发环境也很完善。但是老的浏览器不支持es6规范,尤其是ie浏览器。即使是最新的ie11版本也不完全支持es6规范。这需要对所有原生不支持ES6特性的浏览器进行兼容性处理。本文将针对使用Vue生态开发的网站,基于ie9版本,实现全功能正常使用的全兼容解决方案。ES6兼容ie9环境。不支持es6的一些新对象和表达式。解决办法是使用babel-polyfill组件,可以将es6代码翻译成低版本浏览器可以识别的es5代码。安装完成后,直接引用项目主入口文件main.js第一行即可。在使用vue-cli的项目生成的代码中,根目录下有一个.babelrc文件,这是使用babel的项目的配置文件。在默认生成的模板内容中,添加“useBuiltIns”:“entry”的设置内容,这是一个指定哪些内容需要polyfill(兼容)的设置。useBuiltIns有三个设置选项false-什么都不做入口-根据浏览器版本支持,拆分polyfill要求,只引入浏览器不支持的polyfill使用-检测代码中ES6/7/8的使用,只加载代码中使用的polyfill。这里建议设置为entry,complete.babelrc内容如下:添加这些代码后,工程中的大部分内容都兼容ie9版本的Number对象。即使使用了babel-polyfill进行代码翻译后,发现还有一些es6的新特性没有解决,比如Number对象的parseInt和parseFloat方法es6移植了全局方法parseInt()和parseFloat()到Number对象,并且行为保持完全不变。这样做的目的是逐渐减少全局方法,使语言逐渐模块化。要解决这个问题,不需要引入包来解决这个问题。同样在项目的主入口文件main.js中加入如下代码(代码尽量放在前面,引用babel-polyfill后)。requestAnimationFrame方法window.requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要目的是按帧重绘网页。requestAnimationFrame的好处是充分利用显示的刷新机制,节省系统资源。显示器有固定的刷新率(60Hz或75Hz),也就是说每秒最多只能重绘60次或75次。requestAnimationFrame的基本思想是跟上这个刷新率,用这个刷新率重绘页面。另外,使用这个API,一旦页面不在浏览器的当前标签中,就会自动停止刷新。这节省了CPU、GPU和功率。但是需要注意的一点是,requestAnimationFrame是在主线程上完成的。这意味着如果主线程很忙,requestAnimationFrame的动画效果会大打折扣。window.requestAnimationFrame()方法告诉浏览器您希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法接受一个回调函数作为参数,该回调函数将在浏览器重绘之前被调用。一些第三方组件使用这种方式,比如一些文件上传和图片处理组件;在ie9下使用该类组件时,最新兼容ie版本的window.requestAnimationFrame()会报10。为了兼容ie9,需要做requestAnimationFramepolyfillGist:requestAnimationFramepolyfill代码也会执行http网络请求(跨域)尽量在网站入口处。在大多数web项目中(以JavaWeb为例),网站的页面和服务(至少是controller层)都是在同一个项目中开发和部署的。在大前端新模式下,我们建议网站前后端尽可能完全分离。前后端分离的好处和意义这里就不赘述了。由于前后端分离,部署必须独立。不同的访问路径会造成跨域访问问题(同一个站点,不同的端口号也是跨域的)。此处设置后台:服务端完成启用CROS支持跨域http组件使用axiosaxiossetwithCredentialstotrue启用跨域访问携带cookie数据高版本浏览器(ie10+或chrome,ff)只需要完成后台支持跨域数据请求功能axios在进行数据请求时,默认使用XMLHttpRequest对象。当检测到当前请求是跨域访问时,axios会测试浏览器是否支持XDomainRequest对象。如果它支持它,它将首先使用。ie8/ie9的XMLHttpRequest对象不支持跨域访问,ie10之后该对象原生支持跨域访问。微软的解决方案是在ie8/ie9中提供XDomainRequest(XDR)对象来解决跨域问题。虽然使用这个对象可以使跨域访问成功并返回数据,但它仍然是一个功能不完整的半成品。它的使用有很多限制:XDR只支持GET和POST两种请求方式。XDR不支持自定义请求标头。如果服务端使用header的自定义参数进行鉴权,请求头的Content-Type是不可用的。允许设置为text/plainXDR不允许跨协议请求。如果网页是HTTP协议下的,只能请求HTTP协议下的接口,不能访问HTTPS接口。XDR只接受HTTP/HTTPS请求。发起请求时,不会,虽然微软提供了携带认证或者cookie的方案,但是是不折不扣的鸡肋,不能满足系统中各种场景的数据请求需求。至此,axios对ie9的跨域数据请求无能为力。***解决方案:Proxy(代理)虽然axios对于ie9跨域无能为力,但是前端项目打包的解决方案webpack提供了一个优雅彻底的解决方案:代理devServer.proxywebpack的devServer的功能。proxy由http-proxy-middleware项目提供,其实现原理是将目标位置的请求代理为前端服务本地请求。由于代理变成本地请求,不存在跨域问题,axios会使用XMLHttpRequest对象进行数据处理。请求,一切恢复正常,headers、cookies、content-type、authentication等内容都正确传递给了服务端。项目中webpack.config.js的configuration配置指定http://localhost:8081/myserver服务的位置被代理为本地前端服务的http://localhost:8080/api。比如原来读取用户信息的请求是http://localhost:8081/myserver/user/zhangsan。代理后变成http://localhost:8080/api/user/zhangsan。即/api的前缀代表服务器,所以在使用axios时,需要在每次服务器请求时加上/api的前缀;通常在项目开发中,需要重新封装数据请求组件axios来实现默认参数的统一设置,统一的数据请求入口等,那么只需要在二次包文件中统一调整请求前缀即可这次。但是,webpack的devServer.proxy只能在开发模式下使用,不能在生产模式下使用。在开发模式下,调试服务可以读取webpack.config.js中的配置内容进行实时代理。在将项目部署到生产环境之前,需要对项目进行编译并转为静态js文件。没有调试服务的支持,自然无法请求代理。nginx配置虽然devServer.proxy的功能只能在开发模式下起作用,但是在生产模式下自然有解决方案;通常,Vue项目编译成最终的js文件后,只需要一个静态服务器即可。以nginx为最佳选择,轻量、高性能、高并发、反向代理服务都是它的优点。这里需要做的数据请求代理功能使用nginx的反向代理功能conf/nginx在.conf文件配置中添加如下内容。此配置还将http://localhost:8081/myserver/的目标服务器位置代理到本地服务的/api路径。这样一来,生产环境中的数据请求问题也就解决了。
