IE8 兼容性问题总结

    最近公司的项目要求兼容ie,因为客户需求需要兼容到ie8,接手项目时,技术架构已经形成 :webpack + gulp+ es6 +jquery 。在兼容ie8过程,遇到过一些问题,总结如下。


1. Object.definePrototype 问题

    webpack对js代码处理过程中,会引入Object.definePrototype方法,该方法ie8中并未完全实现。网上有很多教程,其中有通过配置.babelrc为es2005-loose

    {
      "presets": [
      "es2015-loose",
       "stage-0"
      ]
    }

    也有说通过引入shim、sham文件等,但是好像都不起作用。经过多次测试发现,项目中含有 Object.definePrototype部分的代码没有实际作用。此处采用了一种比较暴力的方法,直接删除该部分代码。考虑每次上线发布需要手动删除该部分,可能会因为某次忘记删除导致线上错误,于是通过node编写了一个简单的脚本,然后再打包执行时集成该脚本的运行文件。 脚本replace.js如下:

        /*** Created by zhengchangshun on 2017/10/16.
         * ie8 兼容时, Object.defineProperty 手动去除,暂时未发现有什么影响
         *  dev下,如需兼容ie8,请自行手动执行 node ./replace.js  dev
         */
        var fs = require('fs');
        var path = require('path');
        var name = '';
        // 开发、生成 的代码路径
        var config = {
            "dev": "./dev/js/",
            "dist": "./dist/js/"
        }
        //获取运行的环境
        var args = process.argv[2];
        fs.readdirSync(path.resolve(config[args])).forEach(function (v) {
            if (v.indexOf('common') > -1) {
                name = path.resolve(config[args], v);
                return;
            }
        })
            //读取内容,并将 Object.defineProperty 去除
            var content = fs.readFileSync(name, 'utf-8')
            var reg = /Object\.defineProperty\([\s\S]*?\}\)\;/mg
            content = content.replace(reg, '');
            fs.writeFileSync(name, content, 'utf-8')
  • package.json配置:
        "scripts": {
           ...........
            "build": "gulp build && node ./replace.js  dist",
          .........

*ps: 我只对common.js中的Object.definePrototype做处理,通过正则表达式匹配
Object.definePrototype( ……..}),然后将该部分代码替换为空子字符串。当前前提是必须保证删除该部分代码不会对程序造成影响。*

2. 动态脚本

    由于项目需要,可能会用到动态脚本加载。一般方法如下:

        var Script = document.createElement('script');
        Script.id = 'id';
        Script.type = 'text/javascript';
        Script.src = 'yourScriptUrl'

    在ie8中,动态修改script的src属性会报错,解决办法:调用jquery的getScript()方法,如下:

        $.getScript(yourScriptUrl)

3. CSS文件大小限制

    项目发布到线上时,通常会对css文件进行打包压缩,以节省空间。通常过程中,项目开发过程中会引入一些样式库文件。库文件一起打包,生成的合并文件就会变大。在chrome、FF、IE9以上没有问题,但是在ie8中,样式不显示。调试过程中,开始觉得很诡异,突然一个想法怀疑是ie8对css文件大小有限制,经过查资料,得到如下结论:

  • Up to 31 CSS files or tags per page. 单个页面最多31个css文件
  • Up to 288K per CSS file (uncompressed). 每个css文件大小最大288k
  • Up to 4095 selectors per CSS file. 每个css文件最多4095个选择器

    确实是ie8对css文件的字节数有限制。解决办法:css、less等库文件打包时,可以打包成2至3个文件。

4. window.location.orign

    ie8不支持window.location.orign方法,取值为undefined。解决方法:通过协议、主机、端口拼,重写改属性

        if (!window.location.origin) {
            window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port : '');
        }
        window.location.href = window.location.origin;

5. ajax请求缓存

     在ie8浏览器中,对于同一接口多次请求,会从浏览器的缓存中获取,解决方法:添加时间戳

 url: 'yourAjaxUrl?time=' + new Date().getTime()

6. console问题

    
一般这个问题的现象是:当你开发控制台时不报错,关闭控制台运行代码时报错。window.console()在ie8中必须打开控制台才能实现,关闭控制台时会报错,在ie9才开始修复该问题。解决这个兼容性问题,有两种方案:
- 去除页面中的console.log()方法 (我是用这种方法处理的,页面中残留的console.log()不多)
- 重写window.console()方法;

        (function () {
            var funcs = ['assert', 'clear', 'count', 'debug', 'dir', 'dirxml',
                'error', 'exception', 'group', 'groupCollapsed', 'groupEnd',
                'info', 'log', 'markTimeline', 'profile', 'profileEnd',
                'table', 'time', 'timeEnd', 'timeStamp', 'trace', 'warn'];
            for(var i=0,l=funcs.length;ivar func = funcs[i];
                if(!console[func])
                    console[func] = function(){};
            }
        })()

7. Array.forEach()兼容

    
forEach在ie8中不兼容,重写该方法:

    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++;
            }
        };
    }

8. oninput与onpropertychange

    
有时候需要兼容input输入框的值动态的变化,当然onKeyup也是一种方法,但是对于用鼠标复制等无法监听,onchange需要值有变化时才出发。所以oninput方法比较合适,但是在ie8以下未被兼容,可以通过onpropertychange处理,代码如下:

        Ev.on(ele,"input propertychange",function(e){
           // do something 
        });

9. String.trim()兼容

    
ie8下不兼容String.trim()方法,判断String作用域链上是否存在trim方法,如不存在,就自定义改方法

        // string  trim 方法兼容
        if (!String.prototype.trim) {
            String.prototype.trim = function trim() {
                return this.replace(/^\s+|\s+$/g, '');
            }
        }

有道云笔记地址:http://note.youdao.com/noteshare?id=db7257e244c466caad5a6f0cd8c131f7

你可能感兴趣的:(JavaScript)