神州之心项目总结

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补丁文件,放入项目中

image

然后在页面中引用

<!-- [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.饼图默认选中某条数据的功能实现

  • 想要达成的效果:如图,页面加载完成之后,默认选中最大数据的那一项,当鼠标移到其他项时,取消默认选中,当鼠标移开图表时,回复图表的默认选中。


    QQ截图20180119155953.png
  • 实现方法
    默认选中时,使用图表实例的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方法时使用


QQ截图20180119164830.png
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来代替绘制图表。但是其绘制出来的图表的层级很高,导致了其覆盖了我们项目中的其他的弹窗等

例如:
QQ截图20180119172736.png
就会产生如下情况:
QQ截图20180119172653.png

解决办法,针对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识别*/
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343