IE8下使用react总结

IE8下使用React开发总结


  说到IE,总是令人头疼的,说到IE8,更是令人望而生畏,最近的项目就苦逼的遇上了兼容IE8的需求,当然,作为一个称职的前端开发人员,面对困难总是义不容辞,勇往直前,敢于面对惨淡的人生。
  在进行了调研之后,最终选择了react+redux+webpack+antd全家桶。不得不说,在拼凑这个全家桶的时候确实花费了不少时间和精力,了解了react0.14以下版本对IE8的兼容,我们根据版本对应发布的时间找到了对应的react-router版本和前端react组件框架antd的版本,分别是

  • react(v0.14.3)
  • react-router(v0.14.3)
  • antd(v0.11.3)

  为了兼容IE8,根据react官方文档,配备了es5-shim,es6-promise,console-polyfill,es3ify-loader等,他们各自解决了什么问题,可以参考这两篇文章,es5-shim主要是提供解决方案,当IE8不支持某方法时,检测是否有这个方法,如果没有,自定义它,es5-shim帮我们做好了这个事情。

  当然除了配置这些基本的东西,在后续的开发中还会持续遇到一些令人蛋疼的问题,别慌,强大的谷歌可以解决一切问题,哪怕花一天时间解决ie8的一个兼容性问题,一旦解决了将来就再也不会出现第二次解决不了同一个问题的情况了,因为你需要做笔记!

react-router路由懒加载

原理: webpack 在编译时,会静态地解析代码中的 require.ensure(),同时将模块添加到一个分开的 chunk 当中。这个新的 chunk 会被 webpack 通过 jsonp 来按需加载。还需要结合react-router路由机制来实现路由组件的按需加载
源码react-router-loader

以下写法webpack会生成warning.[chunckhash].js形式的包。并在路由加载到该页面时加载该组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// routers.js
import { Route, DefaultRoute } from 'react-router';
import React from 'react';
import Home from 'react-router?name=home!./components/home';
import CaseDetail from 'react-router?name=detail!./components/case_detail/case_detail';
import CaseWarning from 'react-router?name=warning!./components/case_warning/case_warning';
var routes = (
<Route>
<DefaultRoute handler={CaseWarning} />
<Route path="/case_detail" handler={CaseDetail} ignoreScrollBehavior />
<Route path="/home" handler={Home} />
{/* <Route path="/param_weight" handler={ParamWeight}/>*/}
</Route>
);
module.exports = routes;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 入口文件index.js部分代码
import 'es5-shim';
import 'es5-shim/es5-sham';
import 'console-polyfill';
import React from 'react';
import Router from 'react-router';
import {render} from 'react-dom';
import { Provider } from 'react-redux';
import routes from './routes';
import './less/main.less';
import configureStore from './store/configureStore';
Object.assign = require('object-assign');
require('es6-promise').polyfill();
const store = configureStore();
Router.run(routes, (Handler) => {
render(
<Provider store={store}>
<Handler />
</Provider>,
document.getElementById('app'));
});

注:

  1. 使用该方法在ie8下面会报错,那是由于代码或第三方软件包中使用默认的保留字,解决方法是在bablerc里面添加插件"transform-es3-property-literals""transform-es3-member-expression-literals"
  2. 在该版本的react-router中,使用handler加载组件,使用Router.run加载路由,和最新版本的react-router略有不同,更加详细的使用可以参考官方文档。
1
2
3
4
5
6
7
8
9
// .bablerc
{
"presets": ["es2015", "react", "stage-0"],
"plugins": [
"transform-runtime",
"transform-es3-property-literals",
"transform-es3-member-expression-literals"
]
}

reactjs定义方法

  react组件监听事件的绑定只需要把函数的引用传给onClick,如果要进行传参,则需要使用箭头函数或者传参数的方式执行,就像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
itemClick = (e) => {
console.log(e.target.getAttribute('data-i'));
}
<div data-i="88" onClick={this.itemClick}>
//或者
itemClick = (num) => {
console.log(num);
}
<div onClick={() => this.itemClick(88)}>
//或者
itemClick = (num) => {
console.log(num);
}
<div onClick={this.itemClick.bind(this, 88)}>

三元运算符

  实践表明,使用三元符号来决定组件是否加载的时候最好不用''空字符串来代替,否则react会将此空字符串渲染成一个空的span标签,那是没有必要的。所以尽量使用null来代替空字符串。

1
this.state.edit ? <div>保存</div> : null

IE8下rgba兼容性

IE8下面使用滤镜filter实现半透明,最好不要使用网上的方法如filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#80636769,endColorstr=#80636769);,这会导致z-index失效,至于具体原因暂时不知,貌似说是ie旧浏览器的过滤器错误导致。[issue][4]

1
2
3
4
5
6
7
8
9
10
.mask{
width: 100%;
height: 100%;
position: fixed;
left: 0px;
top: 0px;
background-color: rgba(99, 103, 105, 0.5);
background-color: rgb(99, 103, 105);
filter:alpha(opacity=50); /*IE8支持*/
}

react列表渲染

  在react中,渲染列表元素的时候,每个子元素最好都有唯一的key,这样可以避免状态改变时重复渲染相同的组件或者元素,这个key值尽量不要使用数组的index,因为使用index,在数组发生push或者shift的时候,即使某个值并没有发生改变,但是由于index改变还是会重复渲染,而使用属性值的id可以减少重复渲染。当然在数组元素不具备id的情况下,为了避免react的warning,目前还是只能使用index作为key值。

1
2
3
4
5
6
{factInfoForm.map(item => (
<div className="basic_content" key={item.enName}>
<div className="tags">
<a onClick={this.goAnchor.bind(this, item.startPos)}>{item.zhName}</a>
</div>
</div>))}

IE8在hash模式下的锚点兼容

由于IE8不支持history模式,但是在hash模式的原理和锚点相同,所以和真正的锚点应用存在了冲突,所以需要手动模拟锚点的跳转滚动和url的改变。不管是vue-router在ie9中还是react-router在ie中解决方案都是一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
goAnchor = (key) => {
let anchor = '';
const url = document.location.href.split('#');
// 点击锚点的情况
if (key) {
anchor = key;
HashLocation.push(`${url[1]}#${anchor}`);
} else {
// 路由进来时已经带锚点的情况
anchor = url[2];
}
const element = document.getElementById(anchor);
if (element) element.scrollIntoView();
}

IE8下使用react的dangerouslySetInnerHTML导致的问题

为了渲染服务返回的带html标签的文本,不得不多处使用react的dangerouslySetInnerHTML危险属性来进行渲染,比如,文章标题和文章内容的html插入,本来chrome上面都用的溜溜的,结果在IE8下面一测试,发现文本有的渲染有的不渲染,至今没有搞明白,我怀疑是接口返回的数据格式有问题?该问题预留,如果有人知道原因,请告知我!!谢谢!

IE8下的font-size问题

开发的时候使用了font: 18px '微软雅黑'的写法在开发环境下测试没有问题,但是一打包发布,就发现字体的大小没有了,原因我暂时不知道,但是改成font-size: 18px就好了

火狐乱入

火狐浏览器存在input的placeholder不垂直居中的问题,可以使用css属性placeholder解决

1
2
3
::placeholder{
line-height: 38px;
}

IE8下的uglifyPlugin打包问题

在开发环境下,测试IE8是正常的,结果大伯啊发布到生产环境的时候gg了,经过排查,发现是webpack插件压缩打包导致的。

首先要注意webpack2不支持ie8,其次,使用webpack1时,需要给UglifyJsPlugin压缩插件配置支持support-ie8'才不会报错!!网上查找的答案大多都过时了,以下配置亲测可用(但是过了今天也要注意该文档的时效性。。),所以找不到解决方法的时候去尝试查看官方commit记录是个绝好的办法。。

1
2
3
4
5
6
7
8
9
10
11
new webpack.optimize.UglifyJsPlugin({
minimize: true,
mangle: false,
output: {
comments: false
},
'support-ie8': true,
compress: {
warnings: false
}
})

IE低版本关于文件上传弹出下载的问题

最近在使用antd做兼容IE8项目的时候使用了upload组件,发现在IE10及以下都会存在这个问题:上传文件成功后倘若服务器返回json数据,那么ie就不能正确解析这个数据,反而会把它当做文件来处理。官方给的解决方案是,在后端返回的时候自定义contype-type为”text/html”,比如在node中这样写

1
res.setHeader('Content-Type', 'text/html');

数组末尾多余逗号

1
var ary = [1,2,3,]

在IE8下会被解析成下面的语句

1
var ary = [1,2,3,null]

所以,请不要手贱多写逗号…定义对象的时候多写逗号倒是不会出错

1
2
3
4
var demo = {
name:"lsf",
}
// 在IE8没问题,据说在IE6/7下会报错

所以,eslint是多么重要。。

如果您觉得受益了,欢迎打赏鼓励。