AngularJS 1.3页面不会在IE8中加载

时间:2014-11-17 17:38:03

标签: javascript angularjs internet-explorer-8

作为一个有角色的用户,我对这个问题的标题感到不寒而栗,因为IE8是邪恶的化身,应该像狂犬病一样被放下。

话虽如此,我想知道是否有其他人遇到过在IE8中加载Angular 1.3的问题,并且在加载之前页面中断并且仅在使用isArray的if条件上报告错误:Object Expected ()函数。 (isArray()也可以在Angular 1.2中找到,所以它让我感到困惑的是它在那里工作但不在1.3)

为了让每个人都理解我的理由,我的公司最近采取了不再支持IE8进行新开发的步骤。但是我们的新UI只需要在初始登录页面上支持IE8,这样用户仍然可以访问支持IE8的旧软件。我希望我可以使用1.3,只需为着陆页写一些小调整,直到它从IE8下面出来。

首要问题:是否可以将Angular 1.3与IE8一起使用,或者在我们完全删除IE8支持之前,我是否会被迫使用1.2?

6 个答案:

答案 0 :(得分:12)

有一种方法,虽然它有点粗糙。以下是您需要在角度加载之前加载的代码,您的应用可能运行。这是垫片/填充物的集合,大部分来自Mozilla Developer Network。

请注意,这只允许AngularJS运行,它不会更新IE8的JS运行时。因此somePromise.catch(...)之类的内容无效,您必须撰写somePromise["catch"](...)

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(searchElement) {
        if (this.length === 0) {
            return -1;
        }
        var n = 0;
        if (arguments.length > 1) {
            n = Number(arguments[1]);
            if (isNaN(n)) {
                n = 0;
            } else if (n !== 0 && n !== Infinity && n !== -Infinity) {
                n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
        }
        if (n >= this.length) {
            return -1;
        }
        var k = n >= 0 ? n : Math.max(this.length - Math.abs(n), 0);
        while (k < this.length) {
            if (k in this && this[k] === searchElement) {
                return k;
            }
            ++k;
        }
        return -1;
    };
}

if (!Array.prototype.filter) {
    Array.prototype.filter = function(fun/*, thisArg*/) {
        if (this === undefined || 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;
    };
}

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

if (!Array.prototype.every) {
    Array.prototype.every = function(callbackfn, thisArg) {
        'use strict';
        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 callbackfn !== 'function') {
            throw new TypeError();
        }
        if (arguments.length > 1) {
            T = thisArg;
        }
        k = 0;
        while (k < len) {

            var kValue;

            if (k in O) {
                kValue = O[k];
                var testResult = callbackfn.call(T, kValue, k, O);
                if (!testResult) {
                    return false;
                }
            }
            k++;
        }
        return true;
    };
}

if (!Object.create) {
    Object.create = (function() {
        var Object = function() {};
        return function (prototype) {
            if (arguments.length > 1) {
                throw new Error('Second argument not supported');
            }
            if (typeof prototype != 'object') {
                throw new TypeError('Argument must be an object');
            }
            Object.prototype = prototype;
            var result = new Object();
            Object.prototype = null;
            return result;
        };
    })();
}

if (!Array.prototype.forEach) {
    Array.prototype.forEach = function(fun /*, thisArg */) {
        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 thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        for (var i = 0; i < len; ++i) {
            if (i in t)
                fun.call(thisArg, t[i], i, t);
        }
    };
}

if (!String.prototype.trim) {
    String.prototype.trim = function() {
        return this.replace(/^\s+|\s+$/gm, '');
    };
}

(function() {
    //$http uses onload instead of onreadystatechange. Need shimming as IE8 doesn't have onload.
    if (new XMLHttpRequest().onload === undefined) {
        var orig = XMLHttpRequest.prototype.send;
        XMLHttpRequest.prototype.send = function() {
            var self = this;
            if (!this.onreadystatechange && this.onload) {
                this.onreadystatechange = function() {
                    if (self.readyState === 4) {
                        self.onload();
                    }
                };
            }
            orig.apply(self, arguments);
        };
    }
})();

if (!Date.now) {
    Date.now = function() {
        return new Date().getTime();
    };
}

if (!Function.prototype.bind) {
    Function.prototype.bind = function(oThis) {
        if (typeof this !== "function") {
            throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
        }
        var aArgs = Array.prototype.slice.call(arguments, 1),
            fToBind = this,
            fNOP = function() {
            },
            fBound = function() {
                return fToBind.apply(this instanceof fNOP && oThis
                        ? this
                        : oThis,
                    aArgs.concat(Array.prototype.slice.call(arguments)));
            };

        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP();

        return fBound;
    };
}

if (!Object.keys) {
    Object.keys = function(object) {
        var keys = [];
        for (var o in object) {
            if (object.hasOwnProperty(o)) {
                keys.push(o);
            }
        }
        return keys;
    };
}

if (!Object.getPrototypeOf) {
    Object.getPrototypeOf = function(object) {
        return object.__proto__ || object.constructor.prototype;
    };
}

如果你有angular-bootstrap,你还需要“修补”angular.min.js文件,因为angular-boostrap使用{in: someCondition},但由于旧的JS运行时in关键字保留,将在代码生成中失败。

查找:var e=(b?"s":'((l&&l.hasOwnProperty("'+a+'"))?l:s)')+"."+a;

替换:var e=(b?"s":'((l&&l.hasOwnProperty("'+a+'"))?l:s)')+"['"+a+"']";

答案 1 :(得分:5)

根据对问题的评论和Zenorbi的回答,Angular 1.3不再在IE8中正确加载。它从未被设计为继续在IE8中工作,因此这不应该让人感到意外。

我实际上提出了一个简单的解决方法,它会使任何IE8用户的页面加载时间稍慢,这对我来说是可以接受的。

使用此代码,我可以简单地加载1.3,如果任何IE8用户加载页面,它只会直接加载角度1.2,只需覆盖任何重复的代码:

<script type="text/javascript" src="target/libraries/angular.min.js"></script>
<!--[if lt IE 9]>
<script type="text/javascript" src="target/libraries/angular-1.2.min.js"></script>
<![endif]-->
<script type="text/javascript" src="target/libraries/angular-route.min.js"></script>
<!--[if lt IE 9]>
<script type="text/javascript" src="target/libraries/angular-route-1.2.min.js"></script>
<![endif]-->

注意:这通常是一种可怕的做法。如果我们正在努力支持IE8用户,我会选择Zenorbi的答案,因为它允许你只加载一个版本的角度。

答案 2 :(得分:5)

根据 SamHuckaby Zenorbi 的答案,我提出了可接受的解决方案,这是他们的想法和本文IF Internet Explorer THEN Do Something Else (A How To...)中的见解的结合< strong> Phil Nash :

     <!--[if !IE]>-->
        <script src="/ui/resources/webjars/angularjs/1.4.0/angular.js"></script>
        <script src="/ui/resources/webjars/angularjs/1.4.0/angular-route.js"></script>
    <!--<![endif]-->

    <!--[if gt IE 8]>
        <script src="/ui/resources/webjars/angularjs/1.4.0/angular.js"></script>
        <script src="/ui/resources/webjars/angularjs/1.4.0/angular-route.js"></script>
    <![endif]-->

    <!--[if lt IE 9]>
        <script type="text/javascript" src="/ui/resources/lib/angularjs/1.2.28/angular.js"></script>
        <script type="text/javascript" src="/ui/resources/lib/angularjs/1.2.28/angular-route.js"></script>
    <![endif]-->

        <script type="text/javascript" src="webjars/es5-shim/4.0.6/es5-shim.js"></script>
        <script type="text/javascript" src="webjars/es6-shim/0.20.2/es6-shim.js"></script>

<!--[if !IE]>-->...<!--<![endif]--> - 条件评论将由IE进行评估,但赢得的内容不会被IE加载,并且会被所有其他浏览器加载

<!--[if gt IE 8]>...<![endif]--> - 条件评论将由IE评估,如果大于IE 8,则会加载脚本

<!--[if lt IE 9]>...<![endif]--> - 条件评论将由IE评估,如果小于IE 9,则会加载脚本。

es5-shimes6-shim都应该从IE8条件评论块中删除,并由所有浏览器检查(并且它不是昂贵的操作),因为我最近发现了Safari存在String.prototype.startsWith()

的问题

是的,我们在第一个和第二个条件评论中有一些代码重复(并且它不能以不同的方式解决)但我们已经零个不需要的脚本加载我们可以关闭我们的任务在这里。

答案 3 :(得分:1)

来自Angular Developer Guide migration docs

  

注意:AngularJS 1.3正在放弃对IE8的支持。阅读更多相关信息   我们的博客。 AngularJS 1.2将继续支持IE8,但核心   团队不打算花时间解决IE8或者特定问题   早。

答案 4 :(得分:1)

Github用户@fergaldoyle maintains a repo 结合了shiming / polyfill和其他补丁策略以保持兼容性。

对于许多解决方案提供商而言,这可能是一个可行的策略

答案 5 :(得分:0)

我尝试了L0lander的答案(这是我首选的答案),但是当使用较旧的角度版本时,其他脚本会抱怨,并且最终无法正常工作。所以,我检查了我的网站的统计数据,0.2%只使用IE8或更低,我不会让自己头疼这么小的人群,所以我只是添加了一条消息,要求IE8或更低版本的用户升级。

body标记后的以下代码添加到您的所有网页:

<!--[if lt IE 9]>
    <div style="text-align: center; font-size: 22px; padding: 20px; background-color: #d14c4c; color: #f3e3e3;">Your version of Internet Explorer is too old for this site to function properly.<br>Please <a href="https://www.google.com/search?q=update+internet+explorer" target="_blank" style="text-decoration: underline; color: #76c880">click here</a> to upgrade to a newer version.</div>
<![endif]-->