小编拿到需求。就是一把梭。然而,后来说要把 React 16 的项目兼容到 IE9+,好吧,继续梭。 以下是我在兼容 IE 时遇到的问题
1:浏览器上打开兼容模式是是白屏
拿到项目时。在一些浏览器上打开 IE 模式是是白屏的。好吧。这个问题其实很好解决,Babel 了解一下。
npm install --save @babel/polyfill
在入口文件上的第一行加上 import '@babel/polyfill'
IE11 终于有东西出来了。舒服舒服
2:Map 和 Set 异常
npm install core-js
入口文件顶部加上
import 'core-js/es6/map'
import 'core-js/es6/set'
3:Promise 报错
npm install --save @babel/polyfill
在入口文件上的第一行加上 import '@babel/polyfill'
是的,解法跟问题 1 一样。
在 浏览器中的 IE 兼容模式调整至 IE9,看似一切正常,但是测试哥们说 IE9 浏览器不行啊。所以我自己用虚拟机搞了个 Win7 调试,emmmm……还真不行…… 在 Win7 的 IE9 浏览器上 报了如下错误
4:无法获取属性 responseText 的值,对象为 null 或未定义
小编在浏览器 用 IE9 兼容模式 疯狂刷新,居然也出现这个报错了,但是页面是正常显示的,这 bug 居然是偶现的。
原项目的请求库采用的是 reqwest 在 npm 上 reqwest 介绍中提到兼容 IE6+,项目在请求的写法采用的是 async / await ,reqwest 说兼容到 IE6+,难道是 babel 的锅?
直到我在浏览器点开报错文件,并整理。看到是 reqwest 的 API success 方法 中的参数报错
还好请求的接口不是很多,所以我尝试的更换了请求库 axios
reqwest({
method:get,
url:url,
data:{data:data},
crossOrigin: true, // cors跨域,服务端与客户端存在cookie等数据凭证交互时需要设置
withCredentials: true
})
// 相对应 Axios
axios.get(url,{data:data},{
crossDomain:true,
withCredentials: true // 表示跨域请求时是否需要使用凭证
})
IE兼容模式 -> done!
IE9 浏览器 -> 这次终于有部分内容渲染出来了!
5:IE9 上的跨域请求
延续上个问题,为什么是部分内容出来,控制台此时显示着“拒绝访问”, google / 百度一下吧
有文章提到是 promise 的兼容问题也会提示“拒绝访问”。但是这个问题是跨域才会出现的。自然排除。
问题原因: IE9 XMLHttpRequest 不支持 CORS
fetch 的 polyfill 采用了 XMLHttpRequest 实现, 但是在 IE9 下面, XMLHttpRequest 是不支持跨域请求的. IE10 的 XMLHttpRequest 支持跨域, 而 IE8, IE9 需要使用 XDomainRequest 来实现跨域.
那就用 XDomainRequest 实现异步请求, 代码:
functionfetchIe9(url, options = {}) => {
if (window.XDomainRequest) {
// https://developer.mozilla.org/en-US/docs/Web/API/XDomainRequest
// only support GET and POST method
// request and response content type should be JSON
// without response status code
returnnewPromise((resolve, reject) => {
constmethod = options.method || 'GET';
consttimeout = options.timeout || 30000;
letdata = options.body || options.params || {};
if (datainstanceofObject) {
data = JSON.stringify(data);
}
constXDR = newXDomainRequest();
XDR.open(method, url);
XDR.timeout = timeout;
XDR.onload = () => {
try {
constjson = JSON.parse(XDR.responseText);
returnresolve(json.data);
} catch (e) {
reject(e);
}
returnreject({});
};
XDR.ontimeout = () => reject('XDomainRequest timeout');
XDR.onerror = () => reject('XDomainRequest error');
XDR.send(data);
});
} else {
// native fetch or polyfill fetch(XMLHttpRequest)
// fetch...
}
}
需要注意的是: XDomainRequest 只支持 GET 和 POST mehtod XDomainRequest 不支持带 cookie XDomainRequest 不能设置 responseType, 通信双方需要约定数据格式 XDomainRequest 的响应没有 response status code
题外话: whatwg-fetch 一直采用 XMLHttpRequest 来做 polyfill, whatwg-fetch1.0+ 不支持 IE9, 并不是因为没有采用 XDomainRequest, 而是因为 IE9 的状态码不符合 fetch 规范, 而 polyfill 的目标是 polyfill 规范, 而不是做兼容.
如果是 JQ 使用的话。推荐 jQuery-ajaxTransport-XDomainRequest,CDN 引入即可,请求方式不变,十分方便
6:点击内容 跳转 无反应 (非 a 链接)
点击跳转的大概逻辑
if(条件1){
console.log(123);
window.location.href = '链接1'
}else{
window.location.href = '链接2'
}
解决方案:
1:需要调出控制台 才可以跳转 把console.log 打印去掉即可
2:定时器,将跳转逻辑异步出来 || 阻止冒泡
总结
一步步解bug的过程是让人奔溃的,但是在需求完成时,成就感真的不是一点点。JQ 在 IE 兼容方面,不得不承认他的优势。时代是在进步的,JQ 或许会随着 IE 的没落而渐渐没有优势,但对于现在来说。IE 想完全退出舞台,可能还言之过早。