文档章节

Vue 兼容 ie9 的全面解决方案

TerryZ
 TerryZ
发布于 06/19 10:11
字数 2420
阅读 3296
收藏 68
点赞 6
评论 16

前言

背景情况

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

Vue 官方对于 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 代码

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"
      }
    ],
    "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 的优势,在于充分利用显示器的刷新机制,比较节省系统资源。显示器有固定的刷新频率(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);
        };
}());

Gist:requestAnimationFrame polyfill

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

http网络请求(跨域)

在大多数的 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 的请求
  • 发起请求的时候,不会携带 authenticationcookies

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

完美解决方案:代理(proxy)

虽然 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': ''
            }
        }
    }
}

配置中指定了将 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 文件配置增加以下内容

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

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

个人原创内容,转载请说明出处

完整内容:https://github.com/TerryZ

© 著作权归作者所有

共有 人打赏支持
TerryZ

TerryZ

粉丝 37
博文 10
码字总数 9190
作品 11
福州
架构师
加载中

评论(16)

TerryZ
TerryZ

引用来自“小纯杰”的评论

说放弃的,估计很多是没做过传统行业的项目吧,不知道中国传统行业还有很多旧系统都是IE么,而且很多都是比较重要的系统,真的能做到全部放弃重做?,而且没发现最近很多公司都在涉足传统行业还有政府项目,阿里制造了解一下,重工业的信息化智能化了解一下,毕竟这些行业还是很有钱的,单单做互联网项目真的能养活这么多公司?

引用来自“DUX”的评论

你这么说 还都用ie6 怎么不兼容IE6

引用来自“小纯杰”的评论

ie6那是太古老,IE8没古老到那种程度,就跟现在都出来ES6了,但是真正支持的浏览器有几个,还不是用es5去模拟的,出了es6你能立刻能放弃es5?大公司的框架都没不敢完全放弃IE8,echart,bootstrap等都有IE8兼容选项,就算用现在最主流的前端工程化开发webpack那一套体系,开发环境你可以不兼容,到了生产环境,一样要添加各种兼容polyfill,兼容性问题能避免?逐步过渡是可以理解的,但是一口一个拒绝一口一个不兼容真的可以这么任性?
是这样,做互联网产品、移动端、小程序、微信端,可以任性点,网站类的,不兼容可不像话,尤其是生产系统
小纯杰
小纯杰

引用来自“小纯杰”的评论

说放弃的,估计很多是没做过传统行业的项目吧,不知道中国传统行业还有很多旧系统都是IE么,而且很多都是比较重要的系统,真的能做到全部放弃重做?,而且没发现最近很多公司都在涉足传统行业还有政府项目,阿里制造了解一下,重工业的信息化智能化了解一下,毕竟这些行业还是很有钱的,单单做互联网项目真的能养活这么多公司?

引用来自“DUX”的评论

你这么说 还都用ie6 怎么不兼容IE6
ie6那是太古老,IE8没古老到那种程度,就跟现在都出来ES6了,但是真正支持的浏览器有几个,还不是用es5去模拟的,出了es6你能立刻能放弃es5?大公司的框架都没不敢完全放弃IE8,echart,bootstrap等都有IE8兼容选项,就算用现在最主流的前端工程化开发webpack那一套体系,开发环境你可以不兼容,到了生产环境,一样要添加各种兼容polyfill,兼容性问题能避免?逐步过渡是可以理解的,但是一口一个拒绝一口一个不兼容真的可以这么任性?
D
DUX

引用来自“小纯杰”的评论

说放弃的,估计很多是没做过传统行业的项目吧,不知道中国传统行业还有很多旧系统都是IE么,而且很多都是比较重要的系统,真的能做到全部放弃重做?,而且没发现最近很多公司都在涉足传统行业还有政府项目,阿里制造了解一下,重工业的信息化智能化了解一下,毕竟这些行业还是很有钱的,单单做互联网项目真的能养活这么多公司?
你这么说 还都用ie6 怎么不兼容IE6
小纯杰
小纯杰
说放弃的,估计很多是没做过传统行业的项目吧,不知道中国传统行业还有很多旧系统都是IE么,而且很多都是比较重要的系统,真的能做到全部放弃重做?,而且没发现最近很多公司都在涉足传统行业还有政府项目,阿里制造了解一下,重工业的信息化智能化了解一下,毕竟这些行业还是很有钱的,单单做互联网项目真的能养活这么多公司?
LinkerLin
LinkerLin
IE还是不容兼容的好,微软太可恶了。
一只囧蟹
一只囧蟹
请放弃IE,为了开发者
TerryZ
TerryZ

引用来自“shijunti”的评论

放弃吧,扶不起的阿斗就要换代
真的可以这么任性吗
shijunti
shijunti
放弃吧,扶不起的阿斗就要换代
长沙大东家
长沙大东家
杀死IE
CrazyPeter
CrazyPeter
不是说Vue-CLI 3版本在打包的时候特别照顾IE进行打包了吗。
解决vue在ie9中的兼容问题

vue 解决ie9的兼容问题 当vue遇见ie9的时候,部署到服务器之后,打开居然是一片空白,vue是支持ie9的,这个时候就需要来一波兼容了 1 2 首先 然后在中的最前面引入 在index.html 加入以下代码...

cacao111
07/10
0
0
iView 发布 1.0 正式版,43 个 UI 组件助力中后台业务开发

时隔半年多,iView 终于迎来了它的第一个正式版本 1.0.0,到目前版本,已经有 43 个常用 UI 组件,从功能和设计上,是最接近 Ant.Design 的 Vue.js 实现。 关于 iView 1.0 GitHub 地址:git...

Aresn
07/04
0
0
使用 Mpvue 开发微信小程序的最佳实践

本文由 授权转发,转载需与GitChat联系。 原文链接 本文作者:美团点评 胡成全 前言 小程序面世一年多以来,给前端开发带来了巨大的影响,有移动应用的地方,就有小程序的踪迹。经过一年多的...

乌骑凤
05/17
0
0
基于 Vue 的前端解决方案 - renren-fast-vue

renren-fast-vue基于vue、element-ui构建开发,实现renren-fast后台管理前端功能,提供一套更优的前端解决方案。 renren-fast-vue基于vue、element-ui构建开发,实现renren-fast后台管理前端...

字母大号被盗了
04/16
0
0
keep-alive:组件级缓存

title: keep-alive组件 date: 2018-06-11 09:13:26 tags: keep-alive Vue vue-router 页面缓存 在Vue构建的单页面应用(SPA)中,路由模块一般使用vue-router。vue-router不保存被切换组件的...

大肥凯
07/09
0
0
Vue进阶(四):使用 Vuex + axios 发送请求

Vue进阶(四):使用 Vuex + axios 发送请求 Vue 原本有一个官方推荐的 ajax 插件 vue-resource,但是自从 Vue 更新到 2.0 之后,官方就不再更新 vue-resource。 目前主流的 Vue 项目,都选择...

sunhuaqiang1
05/05
0
0
vue实践中的常见知识漏洞001

前言 本文主要总结了vue实际开发项目当中应该如何解决一些实际的开发问题,可能你认为很简单,但短时间内也许你并没解决思路的。 建议阅读时间:15-25min 更多精彩内容请关注我掘金主页或者 ...

RobinsonZhang
06/07
0
0
Vue高效UI组件库—iView开发实践

前段时间在微软参加活动,分享了 TalkingData 开源的基于 Vue.js 的高效 UI 组件库 iView 的一些开发经验,现整理成文,和大家探讨。 本文首发于掘金,转载请注明出处和作者。 GitHub:https...

Aresn
07/04
0
0
基于 Vue 的静态网站生成器 - VuePress

VuePress 是一个基于 Vue 的轻量级静态网站生成器,以及为编写技术文档而优化的默认主题。 它是为了满足 Vue 自己的子项目文档的需求而创建的。 VuePress 享用 Vue + webpack 开发环境,在 ...

EvanYou
04/16
0
0
合格前端系列第七弹-移动端开发踩过的一些坑

前言: 两个月前开始全身心投入到公司的一个移动端项目,框架选型是vue,这篇文章也是在花费两个月的时间,项目一期完成之后得空进行的一片总结性文章,其中包括通用的移动端开发的坑以及vue...

qiangdada
2017/10/24
0
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

shell中的函数、shell中的数组、告警系统需求分析

shell中的函数 格式: 格式: function f_name() { command } 函数必须要放在最前面 示例1(用来打印参数) 示例2(用于定义加法) 示例3(用于显示IP) shell中的数组 shell中的数组1 定义数...

Zhouliang6
今天
2
0
用 Scikit-Learn 和 Pandas 学习线性回归

      对于想深入了解线性回归的童鞋,这里给出一个完整的例子,详细学完这个例子,对用scikit-learn来运行线性回归,评估模型不会有什么问题了。 1. 获取数据,定义问题     没有...

wangxuwei
今天
1
0
MAC安装MAVEN

一:下载maven压缩包(Zip或tar可选),解压压缩包 二:打开终端输入:vim ~/.bash_profile(如果找不到该文件新建一个:touch ./bash_profile) 三:输入i 四:输入maven环境变量配置 MAVEN_HO...

WALK_MAN
今天
0
0
33.iptables备份与恢复 firewalld的9个zone以及操作 service的操作

10.19 iptables规则备份和恢复 10.20 firewalld的9个zone 10.21 firewalld关于zone的操作 10.22 firewalld关于service的操作 10.19 iptables规则备份和恢复: ~1. 保存和备份iptables规则 ~2...

王鑫linux
今天
2
0
大数据教程(2.11):keeperalived+nginx高可用集群搭建教程

上一章节博主为大家介绍了目前大型互联网项目的系统架构体系,相信大家应该注意到其中很重要的一块知识nginx技术,在本节博主将为大家分享nginx的相关技术以及配置过程。 一、nginx相关概念 ...

em_aaron
今天
1
0
Apache Directory Studio连接Weblogic内置LDAP

OBIEE默认使用Weblogic内置LDAP管理用户及组。 要整理已存在的用户及组,此前办法是导出安全数据,文本编辑器打开认证文件,使用正则表达式获取用户及组的信息。 后来想到直接用Apache Dire...

wffger
今天
2
0
HFS

FS,它是一种上传文件的软件。 专为个人用户所设计的 HTTP 档案系统 - Http File Server,如果您觉得架设 FTP Server 太麻烦,那么这个软件可以提供您更方便的档案传输系统,下载后无须安装,...

garkey
今天
1
0
Java IO类库之BufferedInputStream

一、BufferedInputStream介绍 /** * A <code>BufferedInputStream</code> adds * functionality to another input stream-namely, * the ability to buffer the input and to * sup......

老韭菜
今天
0
0
STM 32 窗口看门狗

http://bbs.elecfans.com/jishu_805708_1_1.html https://blog.csdn.net/a1985831055/article/details/77404131...

whoisliang
昨天
1
0
Dubbo解析(六)-服务调用

当dubbo消费方和提供方都发布和引用完成后,第四步就是消费方调用提供方。 还是以dubbo的DemoService举例 -- 提供方<dubbo:application name="demo-provider"/><dubbo:registry address="z...

青离
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部