1 序言

ps:第四节写了我碰到的问题和解决办法,对前面不感兴趣的可以直接跳到那里
在项目的进行中,原有的正常显示在win7系统中出现许多异常,原因是因为win7自带的ie版本是ie8,而现金常用的win10自带的是ie11,在编写代码的时候没有考虑周全是一点,另外一点需要注意的是,即使在win10环境下把当前ie调节成ie8,器兼容性的测试也是存在差异的,部分在ie8中无法兼容的函数,在win10 中的ie8中兼容(如Array.isArray),暂时未找到具体原因。因此在项目中需要兼容ie8的许多内容。

2 开端

因为习惯了框架的写法,突然转到原生jquery的世界还有许多不足的地方,很多的操作都是边查边写,也闹出了不少那种在内行里看来滑稽的操作手法,不过能实现就行了(强行阿Q)。当时问了大佬这种原生兼容性的有什么比较好的,快捷的,方便的写法,被推荐引入polyfill,被框架惯坏了的人,是真的要去多补充一点babel和webpack相关的知识了,在polyfill的帮助下,我可以尽量少的去更改我原有的一些习惯写法,这一切都是那么的完美,工作进度也正常的推进,完成了编写后,自己简单的测试一下,没有任何异常,直到测试打开了win7系统,不能说是全部不能用,也就大部分直接炸穿,样式畸形,接口返回异常。

3 原因

兼容性异常的问题主要集中在以下几个部分:

  1. 样式异常:具体表现就是移位错位,这部分相对来说好改,之前考虑了部分样式兼容的问题;
  2. 对象不存在:通常来说就是你想用的这个快捷方法函数或者功能是在ie8里面不支持的;
  3. ie8不支持跨域访问:如果接口都是get请求还好,但是post跨域是绝对会被毙掉的,手都不给你握,就是这么任性;
  4. 部分事件响应机制的异常,绑定的keydown和你想要的不一致,监听函数写法也存在差异

4 问题和解决办法

以下问题都是在ie8下的兼容解决,不确定在其他环境可以成功

问题:input 无法获取焦点的,怎么点都不显示

解决办法:input 不能设置为透明背景或者none,另外,ie9以下不支持 type=search image.png

问题:对象不存在

我碰到的主要有以下几种,其中bind是为了使用监听函数引入的
/**
   * @desc 兼容ie6 7 8 JSON
   * @author baidu
   */

  if (!window.JSON) {
    window.JSON = {
      parse: function (jsonStr) {
        return eval("(" + jsonStr + ")");
      },
      stringify: function (jsonObj) {
        var result = "",
          curVal;
        if (jsonObj === null) {
          return String(jsonObj);
        }
        switch (typeof jsonObj) {
          case "number":
          case "boolean":
            return String(jsonObj);
          case "string":
            return '"' + jsonObj + '"';
          case "undefined":
          case "function":
            return undefined;
          default:
            break;
        }

        switch (Object.prototype.toString.call(jsonObj)) {
          case "[object Array]":
            result += "[";
            for (var i = 0, len = jsonObj.length; i < len; i++) {
              curVal = JSON.stringify(jsonObj[i]);
              result += (curVal === undefined ? null : curVal) + ",";
            }
            if (result !== "[") {
              result = result.slice(0, -1);
            }
            result += "]";
            return result;
          case "[object Date]":
            return (
              '"' +
              (jsonObj.toJSON ? jsonObj.toJSON() : jsonObj.toString()) +
              '"'
            );
          case "[object RegExp]":
            return "{}";
          case "[object Object]":
            result += "{";
            for (i in jsonObj) {
              if (jsonObj.hasOwnProperty(i)) {
                curVal = JSON.stringify(jsonObj[i]);
                if (curVal !== undefined) {
                  result += '"' + i + '":' + curVal + ",";
                }
              }
            }
            if (result !== "{") {
              result = result.slice(0, -1);
            }
            result += "}";
            return result;

          case "[object String]":
            return '"' + jsonObj.toString() + '"';
          case "[object Number]":
          case "[object Boolean]":
            return jsonObj.toString();
          default:
            break;
        }
      }
    };
  }

  // 兼容Array.isArray
  if (!Array.isArray) {
    Array.isArray = function (arg) {
      return Object.prototype.toString.call(arg) === "[object Array]";
    };
  }

  // 兼容bind函数
  if (!Function.prototype.bind) {
    Function.prototype.bind = function () {
      if (typeof this !== "function") {
        throw new TypeError(
          "Function.prototype.bind - what is trying to be bound is not callable"
        );
      }
      var _this = this;
      var obj = arguments[0];
      var ags = Array.prototype.slice.call(arguments, 1);
      return function () {
        _this.apply(obj, ags);
      };
    };
  }

问题:也是对象不存在,不过时监听函数

我因为有对页面中的iframe传message,还有就是全局监听单击事件,所有需要addEventListenerremoveEventListener,然而在ie8中不支持,还有一点很重要的就是,在ie8中不能直接写window.attachEvent("onkeydown", keyDownSaveAs());这样的,他会异常,必须要写function套住才行,具体实现办法如下:
    // 监听函数
    if (window.attachEvent) {
      window.attachEvent("onkeydown", function (e) {
        // keyDownSaveAs(e); 这里写自己的函数方法
        stopDefault(e);
      });
    } else if (window.addEventListener) {
      window.addEventListener("keydown", function (e) {
        // keyDownSaveAs(e); 这里写自己的函数方法
        stopDefault(e);
      });
    }

   //阻止默认浏览器行为
  function stopDefault(e) {
    //如果提供了事件对象,则这是一个非IE浏览器
    if (e && e.preventDefault) {
      //阻止默认浏览器动作(W3C)
      e.preventDefault();
    } else {
      //IE中阻止函数器默认动作的方式
      window.event.returnValue = false;
    }
    return false;
  }
  
  // 解除监听
  if (window.removeEventListener) {
      window.removeEventListener("keydown", keyDownSaveAs, false);
  } else {
      window.detachEvent("onkeydown", keyDownSaveAs.bind(window));
  }

问题:post请求无法跨域

讲真,我查了很久,找了很多方法,如果有人碰到了问题,可以先借鉴这位 不认识,但是和我的异常一模一样 的解决办法。但是我在用了所有方法之后还是存在问题,不清楚是不是因为jsp写页面的原因(我也是第一次接触jsp),然后就向后端大佬求救,他把原来的接口映射到了当前域名,就没有了跨域问题了。。。。。

问题:在ie8上和ie10以上的环境中,float布局存在差异

这东西是真的莫名其妙,我一开始对于项目中的左右布局使用的是传统的float布局方式,代码方案如 这个链接里面的方案,然而ie的差异性,让我的布局出现了极大的异常,ie8能正常显示,ie11则左右颠倒,并且存在一定的重叠区域。这个可能是我其他布局引起的,但是项目进度让我没有太多的时间去查找具体原因,使用了第二套解决方案,绝对定位,简单的说就是设置左右两个区域的容器绝对靠左或靠右,然后用padding来控制重叠区域:
.aside{
  position:absolute;
  top: 0px;
  left: 0px;
  padding-right: 300px;
  box-sizing: border-box;
}

.bside{
  position:absolute;
  top: 0px;
  right: 0px;
  box-sizing: border-box;
}

ps2:真的真的真的记得写兼容性前对不确定的方法函数查一下 Can I Use 会少走很多弯路


Cyearn
64 声望2 粉丝