最近项目兼容ie8-10心得

1、ie10及以下浏览器添加了绝对定位的元素,绑定事件无效,需要给元素添加背景色

方法一:
ie9-10:background:rgba(255,255,255,0);
ie8:background:url(about:blank)(ie8不兼容rgba)
方法二:
设置元素背景色后设置透明度为0,(ie8:filter:alpha(opacity=0))
但是这种方式有个缺点,如果元素内有其他内容,其他内容透明度也会变成0

2、ie8-9不兼容表单placeholder属性,通过模拟生成其它标签实现placeholder效果

function placeholderSupport() {
  return 'placeholder' in document.createElement('input');
}

function placeholderRender() {
  //兼容ie9不支持placeholder标签
  if (!placeholderSupport()) {   // 判断浏览器是否支持 placeholder
    function GetStringNumValue(pxstr) {
      return pxstr.substring(0, pxstr.length - 2);
    }

    if ($('input[placeholder],textarea[placeholder]').parents('#formBuild-ie8').length) {
      return false;
    }
    $('input[placeholder],textarea[placeholder]').each(function () {
      var $element = $(this),
        placeholder = $element.attr('placeholder');

      if (placeholder) {
        // 文本框ID
        var elementId = $element.attr('id');
        if (!elementId) {
          var now = new Date();
          elementId = 'lbl_placeholder' + now.getSeconds() + now.getMilliseconds();
          $element.attr('id', elementId);
        }
      }
       // 添加label标签,用于显示placeholder的值
      var $label = $('<label>', {
        html: $element.val() ? '' : placeholder,
        'for': elementId,
        css: {
          position: 'absolute',
          cursor: 'text',
          color: '#ccc',
          fontSize: $element.css('fontSize'),
          fontFamily: $element.css('fontFamily'),
          zIndex: 9,
        }
      }).insertAfter($element);
      // 绑定事件
      $label.addClass('ie-placeholder')
      var _setPosition = function () {
        $label.css({
          top: '7px',
          left: '30px',
        });
      };
      var _resetPlaceholder = function () {
        if ($element.val()) {
          $label.html(null);
        } else {
          _setPosition();
          $label.html(placeholder);
        }
      };
      _setPosition();
      $element.on('focus blur input keyup propertychange resetplaceholder', _resetPlaceholder);
      /**
      以下代码可省略,为了解决点击表单弹出复杂弹窗选中数据的问题,
      问题:ie9中,点击input弹出复杂弹窗后选中数据赋值到input中,模拟出来的placeholder内容还存在,导致选中的数据和placeholder内容重叠
      原因:ie9的propertychange在失去焦点后不会触发
      解决:使用定时器来绑定了此方法!如果认为此方式耗性能,建议不要给该项添加placeholder属性
      **/
      if (isIE9 && $element.attr('readonly')){
        $element.click(function(){
          var intervalName;
          intervalName = setInterval(function () {
            $element.trigger("propertychange");
            if ($element.val()){
              clearInterval(intervalName);
            }else{
            }
          },1000);
        });
      }
    });
  }
}

效果(ie8):


image.png

image.png

label为生成的模拟placeholder效果的标签。

上面css样式可根据项目需求自行设置。
如上面注释中存在的问题,ie9的propertychange在失去焦点后不会触发,面对类似注释中比较复杂特殊的交互,使用了这种比较耗性能的方式解决,或者可以不要给该项设置placeholder,有其他更好的解决方式可以一起讨论。

3、ie8-9中ajax请求不支持跨域,设置允许跨域jQuery.support.cors = true;也不支持

原因:IE10+ 才支持withCredentials属性,IE9以下不支持,跨域对象只能用XDomainRequest对象,而jQuery并不兼容XDomainRequest。
解决:
方法一:设置ie浏览器配置,“工具->Internet 选项->安全->自定义级别”将“其他”选项中的“通过域访问数据源”选中为“启用”(不太现实,无法操控用户设置)
方法二:别跨域请求了,前端配个nginx转发代理吧。(目前的项目采用的这种方式)
方法三:插件 jQuery-ajaxTransport-XDomainRequest,这是一个基于 XDomainRequest 实现 jquery ajxa 的 jquery 插件,为了支持 IE8、9的cors
PS:这里只是说jquery的ajax请求,不包括XMLHttpRequest等。

4、ie8不兼容css :nth-child()

但是.........它兼容jquery的:nth-child()............
emmmmmmmm........
所以css文件中正常这么设置的样式

.index_bg .mainmenu li:nth-child(8n+1) {background-color:#36A1DB}
.index_bg .mainmenu li:nth-child(8n+2) {background-color:#678ce1}
.index_bg .mainmenu li:nth-child(8n+3) {background-color:#8c67df}

要兼容ie8的话,在js中:

if (isIE8) { //isIE8为项目中设置的一个全局变量
      $('.index_bg .mainmenu li:nth-child(8n+1)').css('backgroundColor', '#36A1DB')
      $('.index_bg .mainmenu li:nth-child(8n+2)').css('backgroundColor', '#678ce1')
      $('.index_bg .mainmenu li:nth-child(8n+3)').css('backgroundColor', '#8c67df')
    }

ie8也不兼容很多css3新属性,border-radius、box-shadow、background 背景渐变等,如果需求有这些,要么干掉需求,要么百度。

5、ie8不兼容各种操作数组或者对象很顺手的api,比如filter、forEach、map、Object.assign()、Object.keys()等等等等。。。

兼容:

//filter
if (!Array.prototype.filter) {
    Array.prototype.filter = function (fun ) {
      if (this === void 0 || this === null)
        throw new TypeError();
      var t = Object(this);
      var len = t.length >>> 0;
      if (typeof fun !== "function")
        throw new TypeError();
      var res = [];
      var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
      for (var i = 0; i < len; i++) {
        if (i in t) {
          var val = t[i];
          if (fun.call(thisArg, val, i, t))
            res.push(val);
        }
      }
      return res;
    };
  }

//forEach
if (!Array.prototype.forEach) {

    Array.prototype.forEach = function forEach(callback, thisArg) {

      var T, k;

      if (this == null) {
        throw new TypeError("this is null or not defined");
      }
      var O = Object(this);
      var len = O.length >>> 0;
      if (typeof callback !== "function") {
        throw new TypeError(callback + " is not a function");
      }
      if (arguments.length > 1) {
        T = thisArg;
      }
      k = 0;
      while (k < len) {
        var kValue;
        if (k in O) {
          kValue = O[k];
          callback.call(T, kValue, k, O);
        }
        k++;
      }
    };
  }

//map
if (typeof Array.prototype.map != "function") {
    Array.prototype.map = function (fn, context) {
      var arr = [];
      if (typeof fn === "function") {
        for (var k = 0, length = this.length; k < length; k++) {
          arr.push(fn.call(context, this[k], k, this));
        }
      }
      return arr;
    };
  }

//Object.assign()
if (typeof Object.assign != 'function') {
    Object.assign = function(target) {
      'use strict';
      if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object');
      }
      target = Object(target);
      for (var index = 1; index < arguments.length; index++) {
        var source = arguments[index];
        if (source != null) {
          for (var key in source) {
            if (Object.prototype.hasOwnProperty.call(source, key)) {
              target[key] = source[key];
            }
          }
        }
      }
      return target;
    };
  }

//Object.keys()
var DONT_ENUM = "propertyIsEnumerable,isPrototypeOf,hasOwnProperty,toLocaleString,toString,valueOf,constructor".split(","),
    hasOwn = ({}).hasOwnProperty;
  for (var i in {
    toString: 1
  }) {
    DONT_ENUM = false;
  }
  Object.keys = Object.keys || function (obj) {//ecma262v5 15.2.3.14
    var result = [];
    for (var key in obj) if (hasOwn.call(obj, key)) {
      result.push(key);
    }
    if (DONT_ENUM && obj) {
      for (var i = 0; key = DONT_ENUM[i++];) {
        if (hasOwn.call(obj, key)) {
          result.push(key);
        }
      }
    }
    return result;
  };

都是从网上撸来的兼容方案。

6、IE8不识别媒体查询media

百度文件respond.min.js,引入到用到的文件中的条件注释里

  <!--[if IE 8]>
  <script src="respond.min.js"></script>
  <![endif]-->

注意:媒体查询在IE8里简写不生效。

7、ie中a标签的disabled属性

实际上,a标签没有disabled属性
但是,如果a标签中添加disabled属性,在ie中a标签点击事件无效
(本来也没想到会给a标签添加disabled属性,奈何可爱的后端同事们自己写功能的时候以为disabled对所有标签有效就乱加,以至于发现了这个奇怪的现象。)

8、console.log()在ie8中的猫腻

比较坑的一个问题,现在都是用的ie11仿真模式调试ie8浏览器,一般都是打开控制台调试,控制台关了之后仿真的ie8其实不准确,所以开发是没有关控制台,就没发现问题。
直到项目组用的时候发现了问题,就装了个虚拟机用真实ie8调试,发现某个功能有问题,f12开发者工具打开之后就正常了(也是测了很久才发现f12打开才正常)。
解决:删掉console.log(),IE8会将console.log()默认处理为错误逻辑,但是在F12下处理为控制台输出

持续更新中。。。。(或许)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 夜莺2517阅读 127,881评论 1 9
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 12,758评论 28 53
  • 兔子虽然是枚小硕 但学校的硕士四人寝不够 就被分到了博士楼里 两人一间 在学校的最西边 靠山 兔子的室友身体不好 ...
    待业的兔子阅读 7,543评论 2 9
  • 信任包括信任自己和信任他人 很多时候,很多事情,失败、遗憾、错过,源于不自信,不信任他人 觉得自己做不成,别人做不...
    吴氵晃阅读 11,361评论 4 8

友情链接更多精彩内容