项目使用React
16,控件库用Antd,要求兼容到IE9,所以最近两周一直在搞IE9的兼容性问题。一个原因是因为Antd整体上还是支持IE9的,但是在某些细节地方的兼容性做的并不是很好,需要开发人员自己想办法。上一篇文章中遇到的Webpack4打包后在IE9中遇到的问题现在回头看看,只能说是开了一个
“好“头。
IE9引发的血案-如何处理webpack打包后体积依然过大的css文件
<https://blog.csdn.net/napoleonxxx/article/details/80292006>
按理说,在Webpack,Babel这些工具的帮助下,浏览器兼容性问题不应该成为一个block产品交付的瓶颈,但是这个问题的的确确发生了。凡事总有两面性,尽管处理类似问题很麻烦,但是也通过这个机会让我体会到了两件事,那就是
打包工具能做什么不能做什么,浏览器特别是IE9能做什么不能做什么
以下是问题的汇总,有些是常见的,但是既然我遇到了也就写下来。
* IE9不能支持FormData
* IE9不能支持文件(File) 接口
* IE9不能识别application/json
* IE9不支持以e.target.value的方式取Dom组件的value值(Input, Select etc…)
* IE9不支持很多CSS3特性,比如animation
* IE9不支持H5 Input控件(如select, email etc..)
* IE9不能完全解析体积大于250k的css文件
* 在设置滚动条overflow的情况下,不断滚动会导致底部出现大片空白(chrome, firefox无此类问题)
* IE9下React不支持BrowserRouter,支持HashRouter
IE9不能支持FormData <https://developer.mozilla.org/zh-CN/docs/Web/API/FormData>和
文件(File)接口 <https://developer.mozilla.org/zh-CN/docs/Web/API/File>
项目使用的组件库是Antd <http://ant.design/index-cn>
,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全部会被冲掉,这显然是不行的,很多提交表单后的业务逻辑会无以为继。
废话不说了,直接上解决方法:
* jquery-form <https://www.npmjs.com/package/jquery-form>: 这个库可以帮助我们将原生的html
from提交过程ajax化。(通过源码可以得知本质上还是过将form表单的target指向隐藏的iframe来实现页面中表单的无刷新提交,由iframe的’load’事件callback来处理后续逻辑)
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) { ... } }); }; }
* 为每个表单控件创建一个Hidden Input,value值绑定state
。这样做的好处是我们不用去维护页面中的state,还是交与Redux去处理,我们只需绑定好终值就可以了。 <RadioGroup onChange=
{this.setType} value{this.state.type}> <Radio value={1}>本地上传</Radio> <Radio
value={2}>HDFS</Radio> </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() { <Form.Item >
{this.props.form.getFieldDecorator('createProjectName', { initialValue:
{this.initialValue}, rules: nameRules, getValueFromEvent:
this.getValueFromEvent })( <Input /> )} </Form.Item> }...
以上代码需要注意的是,我们项目中用的是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
<https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState>
import {HashRouter as Router, Route, Switch, Redirect} from 'react-router-dom'
;
经过几天的奋战,IE9的兼容性问题基本解决了。一句话总结React 16在IE9中的使用体验就是:宝马拉破车!
热门工具 换一换