ie8的css兼容性问题
1.不支持box-shadow属性。
解决方法:
使用-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#C7C9CD')";
说明:strength是阴影大小,direction是阴影方位,单位为度,可以为负数,color是阴影颜色 (不支持rgba格式)使用IE滤镜实现盒子阴影的盒子必须是行元素或以行元素显示(block或inline-block;)
box-shadow: 0 5px 10px rgba(33,36,41,0.2);/* for opera or ie9 */
-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#C7C9CD')";
2.不支持rgba()格式的颜色
如果设置的背景色有一个透明度,则ie8及以下都不支持
解决办法:使用filter滤镜设置渐变。设置startColorstr和stopColorstr为相同的颜色,相同的透明度,即可达到半透明的背景效果。其中颜色字符串中,第1,2个字符表示透明度,例如当前的7f表示0.5的透明度,其他值自行去查;后面6个字符既是颜色的十六进制格式。
background-color: rgba(29,61,103,.5);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#7f1D3D67,endColorstr=#7f1D3D67);
3.不支持opacity属性
解决方法: 使用filter滤镜。注意:在使用filter滤镜设置不透明度时,需要给该元素设置背景色,否则设置的不透明度将没有任作用。这个属性一旦设置成功,那么该属性里的元素或者文字都会有设置的透明度。
background: #fff;
opacity: 0;
filter: alpha(opacity=0);/*兼容ie8及以下*/
4.常用的css3选择器的支持性
1)支持:first-child,不支持:last-child选择器,尽量避免使用last-child选择器 。
2)支持:after和:before选择器
3) 不支持:nth-child选择器
4)不支持:not()选择器
5)不支持:checked,:disabled
6)支持属性选择器,如[attribute^=value],[attribute$=value],[attribute*=value]等
5.不支持border-radius属性
解决方法,可通过pie.js补丁文件解决
下载pie补丁文件,放入项目中
然后在页面中引用
<!-- [if it ie 9] -->
<!-- <script src="/static/plugins/pie/PIE.js"></script> -->
<!-- <[!endif] -- >
在css中使用:
border-radius: 4px;
behavior: url(/static/plugins/pie/PIE.htc);
但是使用这个补丁可能会有一些意想不到的问题,所以根据实际情况而定
6.ie9及以下都不支持渐变
解决方法:使用如下方法代替。startColorstr,endColorstr渐变的开始颜色和结束颜色,格式是AARRGGBB,gradiendtType是渐变的方向,1是水平渐变,0是垂直渐变。
progid:DXImageTransform.Microsoft.gradient(startColorstr='#B2FFFFFF',endColorstr='#00FFFFFF',GradientType=0 );
7.其他属性兼容性说明
1)ie9及其以下都不支持css3的@keyframe 规则或 animation 属性,尽量避免使用
2)不支持css3的transform属性(ie9支持代替的-ms-transform属性,仅适用于2D转换
3)不支持background-size属性和border-image属性
8.不支持canvas,和svg
解决方法:使用vml代替,绘制图形
9.不支持placeholder属性
解决方法:自己写一个input组件,使用blur和focus事件来实现placeholder的效果。
import styles from './index.scss';
import React, { Component } from 'react';
import classNames from 'classnames';
class Input extends Component {
constructor(props) {
super(props);
this.state = {
supportPlaceholder: false
};
}
/**
* @param input 输入框
* @param text placeholder
*/
placeholder = (input, text = '') =>{
var defaultValue = input.defaultValue;
if(!defaultValue){
input.val(text).addClass('phcolor');
}
input.unbind('focus', 'F');
input.unbind('blur');
input.focus(function F(){
if(input.val() === text){
$(this).val('');
}
});
input.blur(function(){
if(input.val() === ''){
$(this).val(text).addClass('phcolor');
}
});
// 输入的字符不为灰色
input.keydown(function(){
$(this).removeClass('phcolor');
});
}
componentDidMount() {
let THIS = this;
let self = this.textInput;
this.props.callback && this.props.callback();
$(function(){
// 判断浏览器是否支持placeholder属性
var supportPlaceholder = 'placeholder' in document.createElement('input');
if(!supportPlaceholder){
if($(self).attr('type') === 'text'){
THIS.placeholder($(self), THIS.props.placeholder);
}
}
});
}
componentDidUpdate(){
let supportPlaceholder = 'placeholder' in document.createElement('input');
let self = this.textInput;
let THIS = this;
if($(self).val() || document.activeElement === this.textInput){
return false;
}
if(!supportPlaceholder){
if($(self).attr('type') === 'text'){
THIS.placeholder($(self), THIS.props.placeholder);
}
}
}
render() {
const { supportPlaceholder } = this.state;
let {className, style, ...other} = this.props;
style = style || {
// height: '40px',
// width: 'auto'
};
return (
<input
type="text"
className={classNames('input', 'border_color_gray', 'synBlockBg', className)}
{...other}
style={style}
ref={(input) => { this.textInput = input; }}
/>
);
}
}
export default Input;
ie8的javascript兼容性问题
1.不支持indexOf()方法和trim()方法
在全局js中给string对象添加这两个方法,具体如下
if (!Array.prototype.indexOf){
Array.prototype.indexOf = function(elt /*, from*/)
{
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
};
}
}
2.不支持es6语法,只支持部分es5的语法
解决方法,使用es3ifyPlugin插件,讲es5和es6的语法编译成es3,让ie8完全支持
在配置文件中添加该插件
plugins: [
extractVendor,
extractStyle,
new es3ifyPlugin(),
...
]
项目中遇到的问题
1.饼图默认选中某条数据的功能实现
-
想要达成的效果:如图,页面加载完成之后,默认选中最大数据的那一项,当鼠标移到其他项时,取消默认选中,当鼠标移开图表时,回复图表的默认选中。
- 实现方法
默认选中时,使用图表实例的dispatchAction()方法,代码如下。
/**
* 初始选中最大数据
*/
initBigData = (pieChart = this.pieChart.getEchartsInstance()) => {
const {heightLight} = this.state;
if(heightLight){
setTimeout(() => { // 由于在执行此方法的时候,图表不一定就渲染完毕,所以设置了一个定时器
pieChart.dispatchAction({
type: 'highlight', // 选中
name: heightLight // 选中的项的名字,这里是“私营企业”
});
}, 10);
}
}
方法使用示例,在图表init了之后,获取到实例后,再执行该方法,
renderEchartDom(flag) {
let echartObj = echarts.init(this.echartsDom, themeStrSession);
echartObj.setOption(this.props.option, true, true);
initBigData && initBigData (echartObj); // 饼图默认选择最大的值
return echartObj;
}
移除图表再恢复默认选中的方法
/**
* 取消饼图某个模块的选中状态
*/
reSet = () => {
const {heightLight} = this.state;
if(heightLight){
this.pieChart.getEchartsInstance().dispatchAction({
type: 'downplay', // 取消选中的标识
name: heightLight // 取消选中项的名字
});
}
}
使用时,给图表的外框加一个鼠标移除的事件(mouseleave),在该事件的方法中执行reSet()方法即可。
注意:mouseleave()和mouseout()方法的区别.
mouseout 事件在鼠标指针离开被选元素或任意子元素时都会被触发,mouseleave 事件只有在鼠标指针离开被选元素时被触发。
2.echarts图标的主题色切换
在项目中,有些时候设计到换肤的功能,一套浅色一套深色,这个时候,echarts图表的主题该怎么设置才能满足要求呢。
这时我们使用echarts主题色,配置两套主题,一套深色主题,一套浅色主题,(具体主题色的配置自行查阅)在init方法时使用
require('./echartDarkTheme'); // 引入深色主题
require('./echartLightTheme'); // 引入浅色主题
getEchartsInstance() {
const themeStrSession = sessionStorage.getItem('skinNum') === 'dark' ? 'echartDarkTheme' : 'echartLightTheme';
return echarts.init(this.echartsDom, themeStrSession);
}
3.react事件和原生事件混用所产生的问题
react事件是合成事件,使用了事件委托的方法,将所有的事件绑定在了document上,并且在事件冒泡的过程中执行对应的回调方法。而原生事件是直接绑定在了dom上,所以,当一个dom上用了react绑定了事件,有用原生方法绑定了事件之后,我们并不能确定是哪一次绑定的回调函数会先执行,因此会有很多意想不到的问题,所以我们要尽量避免react和原生事件混用的情况。
4.前端轮询监听报报告是否生成或下载成功
在生成一个报告的过程中,怎么监听报告什么时候生成完毕呢,在前端的话,我们需要轮询
监听方法
/**
* 监听是否生成成功
*/
addListerReport = () => {
const reportInfo = JSON.parse(JSON.stringify(this.state.reportInfo));
const {intervalTime} = this;
addListerReport({
reportId: reportInfo.reportId
}).then(data => {
if(!data.success){
return messager.error('报告生成失败,请重新生成!');
}
if(data.data) {
reportInfo.reportStatus = 'SUCCESS';
clearInterval(intervalTime);
// clearTimeout(outTime);
this.setState({
operateText: '',
reportInfo
});
}
});
}
方法的调用
/**
* 点击生成报告
*/
reGenerateReport = (isNewReport) => {
const reportInfo = JSON.parse(JSON.stringify(this.state.reportInfo));
const {companyId, reportTime, companyName} = reportInfo;
generateReport({
companyId,
companyName,
remakes: isNewReport
}).then(data => {
if(!data.success) {
return messager.error('生成失败,请重新生成!');
}
this.intervalTime = setInterval(() => { // 轮询调用监听方法,每个5秒调用一次
this.addListerReport();
}, 5000);
});
}
注意:在组件卸载之前要先清除该定时器,否则该方法会一直执行
componentWillUnmount() {
const {intervalTime, outTime} = this;
clearInterval(intervalTime);
}
5.地图下潜和返回是总有一种闪现的情况
该情况主要产生的原因是,在下潜时,省的名已经传递给了下层组件,用于绘制,但此时,该省的地图json数据还没有拿到,这时如果其他地方使用了setState,发生了render的话那么下层组件就会重新绘制地图,但是由于省的名字和地图json数据对应不上,就又一次绘制了全国地图,这时就会有一个中间的过程,导致地图闪一下才会绘制出对应的省的地图。
解决办法,省的名字和地图的json数据同时设置,并且同时使用,尽量避免没有必要的渲染。例如:这里一起设置了三个值之后,进行渲染,就不会产生跳动的情况
$.getJSON(mapUrl, (mapjson) => {
this.setState({
jsonData: mapjson, // 地图的json数据
mapChinaOption: option, // option对象
province: this.mapInfo.province }); // 下潜的省市名称
});
6.ie8下使用vml绘制的图表的层级问题
ie8不支持canvas,所以我们使用vml来代替绘制图表。但是其绘制出来的图表的层级很高,导致了其覆盖了我们项目中的其他的弹窗等
解决办法,针对ie8,单独设置弹窗的层级
.bg{
...
opacity: 0.4
z-index: 1000;
z-index: 50020\9;/*给背景蒙层设置层级 IE6、7、8识别*/
filter: alpha(opacity=40);
}
.wrap{
...
z-index: 1000;
z-index: 50020\9;/*给弹窗的外层设置层级 IE6、7、8识别*/
}