最近项目进入到了第三方集成的环节, 集成第三方监控非要用 IE, 咋办? 老板让我将后台管理系统的框架兼容下 IE, 一直都是在 Chrome 下开发的, 也不知道 IE 下是什么鬼.
目前后台管理系统前端搭建方式
目前系统是用 vue-cli@2.0 生成的, UI 框架使用的是 iview,Ajax 请求使用的是 axois, 此外就没有什么特殊的 NPM 包了.
需要解决的兼容问题
经过自己的一番测试, 目前主要有以下的兼容问题:
在 IE 下由于没有 promise, 所以 axios 不能用了;
在涉及到 flex,fixed,absolute 定位时, IE 浏览器下的显示效果有较大的区别;
Excel 表单导出异常;
部分使用的 NPM 包中的代码未经编译会有一些 ES6 的语法;
vue-router 路由失效;
IE 自动缓存 Ajax 请求结果.
如何解决这些问题
解决第一个问题需要在项目中引入 babel-polyfill, 我的处理方式时在 build->webpack.base.config.JS 文件中的添加一下的配置:
解决第二个问题则需要自己写一些兼容性比较好的样式, 在这里我就不做过多的解释了;
第三个问题的解决过程比较的曲折, 系统的下载是同过接口返回文件流的形式进行下载的, 可以看下我原来的代码, 原先通过 axios 的拦截器来获取响应内容的格式, 然后进行下载, 但是在 IE 的兼容测试过程中发现了一个问题, 那就是 axios 在 Chrome 和 IE 下的表现不一致, 具体哪里一致可以简单的说下:
- const downloadUrl = url => {
- let iframe = document.createElement('iframe');
- iframe.style.display = 'none';
- iframe.src = url;
- iframe.onload = function () {
- document.body.removeChild(iframe);
- };
- document.body.appendChild(iframe);
- };
- // 拦截二进制响应流
- if (res.headers && (res.headers['content-type'] === 'application/vnd.ms-excel;charset=UTF-8' || res.headers['content-type'] === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || res.headers['content-type'] === 'application/octet-stream;charset=UTF-8')) {
- downloadUrl(res.request.responseURL);
- return
- }
这里面的问题在于在 IE 浏览器中 res.request.responseURL 这个属性是不存在的, 就算存在了, 在进行文件下载时也会出现异常, 后台看到很多人都出现了这样的问题, 怎么办, 我相信这个问题一定是可以解决的, 虽然没有搜到合适的方案, 但是一个网友提示这一切的问题都是使用了第三方封装的 Ajax 请求, 那为什么不自己手写一个原生的 Ajax 请求呢? 切换思路后发现, 果然是可以的, Ajax 下载文件流可以使用以下代码:
- utils.exportFiles = (type = 'GET', url = null) => {
- var xhr = null
- if (Windows.XMLHttpRequest) { // Mozilla 浏览器
- xhr = new XMLHttpRequest()
- } else {
- if (Windows.ActiveXObject) {
- try {
- xhr = new ActiveXObject('Microsoft.XMLHTTP')
- } catch (e) {
- try {
- xhr = new ActiveXObject('Msxml2.XMLHTTP')
- } catch (e) {
- }
- }
- }
- }
- xhr.open(type, url, true)
- xhr.responseType = 'blob'
- if (type === 'POST') {
- xhr.setRequestHeader('Content-type', 'application/json')
- }
- xhr.onload = function (res) {
- var contentDisposition = xhr.getResponseHeader('content-disposition')
- var contentType = xhr.getResponseHeader('content-type')
- var filename = contentDisposition.split(';')[2]
- // eslint-disable-next-line no-eval
- eval(filename)
- filename = decodeURI(filename)
- if (this.status === 201) {
- var blob = this.response
- if (typeof Windows.navigator.msSaveBlob !== 'undefined') {
- // IE 浏览器进行下载
- Windows.navigator.msSaveBlob(blob, filename)
- } else {
- // 非浏览器进行下载
- var downloadUrl = document.createElement('a')
- downloadUrl.download = filename
- downloadUrl.style.display = 'none'
- downloadUrl.href = URL.createObjectURL(blob)
- document.body.appendChild(downloadUrl)
- downloadUrl.click()
- URL.revokeObjectURL(downloadUrl.href)
- document.body.removeChild(downloadUrl)
- }
- } else {
- console.log('导出错误')
- }
- }
- xhr.send()
- }
第四个问题同样还是一些 webpack 打包的问题, 在 vue-cli2.0 生成的项目中, 哪些 JS 会使用 babel-loader 是这样配置的:
我们可以看到, 其针对 3 个文件加的 JS 代码使用 babel-loader, 将需要使用 babel-loader 的 NPM 包添加到其中即可. 第五个问题百度可以搜到, 其中我比较推荐的解决方案如下:
- const IE11RouterFix = {
- methods: {
- hashChangeHandler: function () {
- this.$router.push(Windows.location.hash.substring(1, Windows.location.hash.length));
- },
- isIE11: function () { return !!Windows.MSInputMethodContext && !!document.documentMode; }
- },
- mounted: function () { if (this.isIE11()) { Windows.addEventListener('hashchange', this.hashChangeHandler); } },
- destroyed: function () { if (this.isIE11()) { Windows.removeEventListener('hashchange', this.hashChangeHandler); } }
- }
- export default IE11RouterFix
- var vm = new Vue({
- el: '#app',
- router,
- store,
- mixins: [IE11RouterFix],
- components: {
- App,
- },
- template: '<App/>'
- });
第 6 个问题是过了一段时候发现的, IE 会自动的缓存请求的结果, 那么对系统中的一些操作是有影响的, 比如说是在数据保存完成之后回到列表页的刷新, 取到的数据是缓存中的数据. 怎么办, 我们可以在 axios 的请求拦截器中自动为请求地址添加时间戳, 保证每次的请求的地址是不一样的.
总结
以上耗时一天的 IE 兼容就完成了, 目前只能兼容到 IE11,IE10, 其他的我已经放弃了, 就算再兼容完成后, 系统再 IE10 下的表现也不是特别的好, 感觉比较卡, 再 IE11 下也只能说是正常.