Vue 兼容 ie9 的全面解决方案

一、兼容IE主要是从以下几个方面考虑

  • es6语法兼容
  • Number对象es6新方法兼容
  • requestAnimationFrame方法兼容
  • axios Promise兼容
  • axios cors兼容

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

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

二、ES6语法兼容

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

npm i babel-polyfill --save-dev

安装完成后,在项目的主入口文件 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",  //添加此属性"targets": {"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]}}],"stage-2"],"plugins": ["transform-vue-jsx", "transform-runtime"]
}

加入这些代码后,工程里的大部分内容已可兼容到 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 的优势,在于充分利用显示器的刷新机制,比较节省系统资源。显示器有固定的刷新频率(60Hz或75Hz),也就是说,每秒最多只能重绘60次或75次,requestAnimationFrame 的基本思想就是与这个刷新频率保持同步,利用这个刷新频率进行页面重绘。此外,使用这个API,一旦页面不处于浏览器的当前标签,就会自动停止刷新。这就节省了CPU、GPU和电力。

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

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

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

SCRIPT5007: Expected object.
window.requestAnimationFrame() 的最低兼容 ie 版本为 10,那么在 ie9 上做兼容就需要制作 requestAnimationFrame polyfill(function() {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(callback, element) {var currTime = new Date().getTime();var timeToCall = Math.max(0, 16 - (currTime - lastTime));var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);lastTime = currTime + timeToCall;return id;};if (!window.cancelAnimationFrame)window.cancelAnimationFrame = function(id) {clearTimeout(id);};
}());

五、axios Promise兼容

由于axios是基于Promise封装的,而整个ie浏览器家族都不支持Promise属性,所以我们要借助插件来解决这个问题。

首先安装开发环境依赖:

npm install es6-promise --save-dev

然后在主入口main.js如下:

import Es6Promise from 'es6-promise' // 引入es6-promise模块
Es6Promise.polyfill() // 挂载模块

然后在ie里面就可以支持promise,使用axios请求数据了。

存在的问题:ie9不支持cors跨域访问。

六、axios cors兼容

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

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

在此设定背景情况:

服务端已完整开启 CROS 跨域支持 http 组件使用 axios axios 设置 withCredentials 为 true
开启跨域访问时携带 cookie 数据 高版本浏览器(ie10+ 或 chrome,
ff)仅需要完成背景情况中的功能,即可支持跨域数据请求功能

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

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

XDR 仅支持 GET 与 POST 两种请求方式 XDR 不支持自定义的请求头,若服务端使用 header
的自定义参数进行做身份验证,则不可用 请求头的 Content-Type 只允许设置为 text/plain XDR
不允许跨协议的请求,如果网页在 HTTP 协议下,就只能请求 HTTP 协议下的接口,不能访问 HTTPS 接口 XDR
只接受HTTP/HTTPS 的请求 发起请求的时候,不会携带 authentication 或 cookies
微软虽然提供了解决方案,但却是不折不扣的鸡肋,根本无法胜任系统中各种场景的数据请求需求,至此,axios 对 ie9
的跨域数据请求已无能为力。

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

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

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

在项目中config文件夹下的index.js dev对象中添加proxy代理配置

dev: {proxy: {'/api': { // 匹配请求代理的路径,如果请求路径是/api,则采用对应proxy代理target: 'https://guojiongwei.com', // 代理的接口地址pathRewrite: {'^/api' : ''}, // 真正发起请求的适合把/api重置为空changeOrigin: true // 是否允许跨域请求}}
}
然后请求时候:axios.get('/api/client_demo_api/blog/list?pagesize=10').then(res => {console.log(res)
})

即是 /api 的前缀代表了服务端,会匹配到proxy配置对应的/api,因为我们在配置的时候对/api进行了置空,所以实际请求到的接口为https://guojiongwei.com/client_demo_api/blog/list?pagesize=10,服务器和服务器之间请求数据是没有跨域限制的,node请求到数据后,允许跨域访问,我们就可以在前端接收到数据了,从而解决了ie9不支持跨域的问题。

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

存在的问题:在webpack中配置的proxy代理只在开发环境有效,项目build打包后就不生效了,所以需要在用托管打包后的静态资源的时候,也配置一下代理。

nginx 代理配置

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

conf/nginx.conf 文件配置增加以下内容location /api/ {proxy_pass https://guojiongwei.com;
}

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

node代理配置

const express = require('express');
const app = express();
const path = require('path');
const proxy = require('http-proxy-middleware');
const compression = require('compression'); //解析gzip格式文件 js,css
const history = require('connect-history-api-fallback'); //解析history路由模式项目
// 和webpack里面配置差不多一致
app.use('/api', proxy({target: 'https://guojiongwei.com',pathRewrite: {'^/api' : '/'},changeOrigin: true
}))
app.use(history());
app.use(compression())
app.use(express.static(path.join(__dirname, './dist'))); //托管打包后的静态资源
// 监听端口
app.listen('4000','0.0.0.0', () => {console.log(`server running localhost:4000`);
});

Vue 兼容 ie9 的解决方案相关推荐

  1. Vue 兼容 ie9 的全面解决方案

    Vue 兼容 ie9 的全面解决方案 参考文章: (1)Vue 兼容 ie9 的全面解决方案 (2)https://www.cnblogs.com/hejun210/p/9228081.html 备忘 ...

  2. vue兼容IE8以上解决方案

    一.说明背景 vue主要采用了ES6 Promise,我们知道的,在 JavaScript 中,所有代码都是单线程的,也就是同步执行的.而 Promise 就为异步编程提供了一种解决方案. 二.解决方 ...

  3. vue2.x兼容ie9+的解决方案与调试

    1.ie9以上的调试 ie控制台若不显示调试内容,可以下载补丁(IE11-Windows6.1-KB3008923-x64.msu),安装之后就好了. 下载链接:https://www.microso ...

  4. vue遇到ie兼容问题如何处理_详解vue 兼容IE报错解决方案

    IE 页面空白 报错信息 此时页面一片空白 报错原因 Babel 默认只转换新的 JavaScript 语法(如箭头函数),而不转换新的 API ,比如 Iterator.Generator.Set. ...

  5. vue 检测ie版本_分析vue 兼容IE报错解决方案

    这篇文章主要为大家详细介绍了分析vue 兼容IE报错解决方案,具有一定的参考价值,可以用来参考一下. 感兴趣的小伙伴,下面一起跟随512笔记的小编两巴掌来看看吧! IE 页面空白 报错信息 [图片暂缺 ...

  6. 解决vue在ie9中的兼容问题

    vue 解决ie9的兼容问题 当vue遇见ie9的时候,部署到服务器之后,打开居然是一片空白,vue是支持ie9的,这个时候就需要来一波兼容了 参考尤大的解答 https://github.com/v ...

  7. React+Webpack+ES6 兼容低版本浏览器(IE9)解决方案

    React+Webpack+ES6 兼容低版本浏览器(IE9)解决方案 参考文章: (1)React+Webpack+ES6 兼容低版本浏览器(IE9)解决方案 (2)https://www.cnbl ...

  8. vue 兼容IE报错解决方案

    vue 兼容IE报错解决方案 参考文章: (1)vue 兼容IE报错解决方案 (2)https://www.cnblogs.com/candymanping/p/10195377.html 备忘一下.

  9. vue上传(兼容IE9)

    项目中vue文件上传功能原来使用的是element ui组件,头像上传裁剪使用的是vue-image-crop-upload,但是这两个组件只支持到IE10+,现在项目要求兼容IE9,这两个组件就没办 ...

最新文章

  1. php 获取日期标签的值,在php中获取标签的选定索引值
  2. Navicat Mac 快捷键有哪些
  3. Java Web学习路线
  4. 《软件工程》实验报告——软件测试
  5. Jquery实现简单图片切换
  6. 递归算法(python),汉诺塔问题,斐波那契数列,一个简单的递归实例,用递归实现阶乘,用递归查看目录及文件
  7. python为什么没有指针_Python中有指针吗?
  8. 【FPN车辆目标检测】数据集获取以及Windows7+TensorFlow+Faster-RCNN+FPN代码环境配置和运行过程实测
  9. 测试环境下将centos6.8升级到centos7的操作记录(转)
  10. Music Bugs : 不支持wma格式的歌曲播放
  11. javacv 视频增加水印
  12. clone git 修改保存路径_SEO优化知识一般需要了解什么代码_学云网
  13. 百度地图坐标系统解析
  14. 新浪开发者平台(Sina App Engine)初探
  15. 2021年10月国产数据库排行榜:达梦反超OceanBase夺榜眼,TDSQL实现“四连增”,数据生态加速建设
  16. 京东云php环境配置,干货 | 京东云应用负载均衡(ALB)多功能实操
  17. java自动装配_Spring中自动装配的4种方式
  18. 数字图像处理中的车牌识别
  19. charles对iOS手机的https进行抓包(图文教程)
  20. cuda9.0+cudnn7.0 +tensorflow1.5(1.6) 报错:ImportError: libcublas.so.9.0: cannot op

热门文章

  1. 清华梦的粉碎—写给清华大学的退学申请 2005.9.22[转贴]
  2. 什么是淘宝关键词以及如何查找关键词的方法
  3. (python基础)各种打印三角形
  4. 怎样将语音翻译成文字?实现语音翻译文字这两招帮你搞定
  5. POJ1151 Atlantis(线段树,扫描线,离散化,矩形面积并)
  6. 从征途中学习社区运营
  7. Kratos战神微服务框架(一)
  8. 「信息安全技术」期末复习宝典 【整理完毕】
  9. android视频编辑sdk官网,LanSoEditor_common ---android平台的视频编辑SDK
  10. L2-009 抢红包 (25 分)