项目使用React 16,控件库用Antd,要求兼容到IE9,所以最近两周一直在搞IE9的兼容性问题。一个原因是因为Antd整体上还是支持IE9的,但是在某些细节地方的兼容性做的并不是很好,需要开发人员自己想办法。上一篇文章中遇到的Webpack4打包后在IE9中遇到的问题现在回头看看,只能说是开了一个“好“头。
IE9引发的血案-如何处理webpack打包后体积依然过大的css文件
按理说,在Webpack,Babel这些工具的帮助下,浏览器兼容性问题不应该成为一个block产品交付的瓶颈,但是这个问题的的确确发生了。凡事总有两面性,尽管处理类似问题很麻烦,但是也通过这个机会让我体会到了两件事,那就是打包工具能做什么不能做什么,浏览器特别是IE9能做什么不能做什么
以下是问题的汇总,有些是常见的,但是既然我遇到了也就写下来。
IE9不能支持FormData和文件(File)接口
项目使用的组件库是Antd,Antd提供了一系列功能丰富的控件。是我们无需把页面控件包含到Form中,我们通过Redux来管理页面控件的状态,点击提交按钮时,通过FormData来构造“模拟表单“键值对进行异步提交。
submit = () => {
let formData = new FormData();
formData.append("type", this.state.type);
...
formData.append("file", $("#file_upload")[0].files[0]);// 获取文件
$.ajax({
url: this.url,
type: 'POST',
data: formData,
success: function (res) {
....
},
error: function (res) {
....
}
});
};
代码中我们既使用了FormData,也调用了File接口,在IE9上妥妥的挂了。如果不用FormData,Ajax就无法提交文件内容,哪怕浏览器支持File接口。FormData作为一个协议,也不存在什么Polyfill(从百度到谷歌,的确是没搜到)。那么能做的也只能是用最原始的form表单提交方法了。最原始的表单提交的最大问题就是会刷新页面,这意味着待提交页面上由Redux保管的state全部会被冲掉,这显然是不行的,很多提交表单后的业务逻辑会无以为继。
废话不说了,直接上解决方法:
require('jquery-form');
componentDidMount() {
// ajaxSubmit正是jquery-form的关键方法
$("#btnSubmitWithFile").click(function () {
$("#importDataForm").ajaxSubmit({
url: this.uploadUrl,
type: "post",
dataType: "json",
success: function (res) {
...
},
error: function (res) {
...
}
});
};
}
<RadioGroup onChange={this.setType}
value{this.state.type}>
<Radio value={1}>本地上传Radio>
<Radio value={2}>HDFSRadio>
RadioGroup>
<Input type="hidden" name="type" value={this.state.type}/>
return <div className="data-view">
<Form id="importDataForm" enctype="multipart/form-data">
{AddFromDom}
<Input type="button" style={{display: "none"}} id="btnSubmitWithFile" value=" 上传" />
Form>
div>
IE9不能识别application/json
这个引发的主要问题是,IE9如果收到content-type为application/json的response,因为无法识别,因此会把他当成一个待下载文件处理,从而导致app无法接收并处理这个response。
这个问题的解决方法就是在后台将response的content-type设置为text/plain。前端注意的就是会接收到string类型的数据,需要用JSON.parse(res)转化成数据格式。
IE9不支持以e.target.value的方式取Dom组件的value值
e.target.value是从IE10开始支持的,所幸IE9中有e.currentTarget.value还可以取得正确的值。
//common.js
getInputValue(e) {
if (!e || !(e.target || e.currentTarget)) {
return e;
}
return e.target.value !== undefined ? e.target.value : e.currentTarget.value;
}
//page.jsx
import common from '../../components/common/common';
getValueFromEvent = e => {
return common.getInputValue(e);
}
render() {
{this.props.form.getFieldDecorator('createProjectName', {
initialValue: {this.initialValue},
rules: nameRules,
getValueFromEvent: this.getValueFromEvent
})(
)}
}
...
以上代码需要注意的是,我们项目中用的是antd的控件,而e.target.value的获取在控件源代码中,还好,antd的Form表单提供了一个option: getValueFromEvent,我们可以在这里修改input事件产生的event对象。
IE9不支持很多CSS3特性,比如animation
一些加载的动画效果无法展现,由于时间与性价比的关系,我们并没有做什么workaround。不会影响功能,不影响用户使用,放在那里也能提醒用户IE9该换啦!!
IE9不支持H5 Input控件(如select, email etc..)
这个没什么好说的,避开使用就行。
在设置滚动条overflow的情况下,不断滚动会导致底部出现大片空白(chrome, firefox无此类问题)
诡异的问题,最后的解决方法来自google,在设置overflow的地方加一个’min-height: 0%;’
IE9下React不支持BrowserRouter,支持HashRouter
这个原因也很简单,BrowserRouter底层需要调用H5中增加的history.pushstate等新函数。
history MDN
import {HashRouter as Router, Route, Switch, Redirect} from 'react-router-dom' ;
经过几天的奋战,IE9的兼容性问题基本解决了。一句话总结React 16在IE9中的使用体验就是:宝马拉破车!