让hashchange事件在所有浏览器中(包括IE7)生效

17

我有一些代码(由另一位开发者编写),它在WordPress中进行AJAX页面加载(例如,没有页面重新加载),当您单击导航项时,AJAX刷新主内容区域。我的问题是它在IE7中出现问题,而我不知道从哪里开始调试。

原始开头是:

var queue = 0;

$('document').ready(function() {
    window.addEventListener("hashchange", hashChange, false);

    // Define window location variables
    var windowHost = window.location.host,
        windowHash = window.location.hash,
        windowPath = window.location.pathname;

但我改变了它们,将addEventListener条件化,基于该方法是否存在。 一些研究告诉我,这个方法在旧版本的IE中不可用(例如,在我的情况下是7)。 此外,IE7调试控制台将其识别为不可用的方法,因此非常明显。 我将这些行重写如下,但代码仍然无法工作:

var queue = 0;

$('document').ready(function() {
    if(window.addEventListener) {
        window.addEventListener("hashchange", hashChange, false);
    }
    else if (window.attachEvent) {
        window.attachEvent("hashchange", hashchange, false);    
    }
    // Define window location variables
    var windowHost = window.location.host,
        windowHash = window.location.hash,
        windowPath = window.location.pathname;

完整的原始脚本可以在此pastebin上查看:http://pastebin.com/Jc9ySvrb

2个回答

31
  • attachEvent需要在事件前加上on前缀。
  • 该方法的大小写不同。将attachEvent中的hashchange更改为hashChange以使该事件在IE8中正常工作。
  • 使用建议的实现来支持IE7-和其他旧浏览器的hashchange实现。

我已经创建了一个跨浏览器的实现,可以将hashchange功能添加到浏览器中,即使那些不支持它的浏览器也可以使用。回退是基于规范的。

//function hashchange  is assumed to exist. This function will fire on hashchange
if (!('onhashchange' in window)) {
    var oldHref = location.href;
    setInterval(function() {
        var newHref = location.href;
        if (oldHref !== newHref) {
            var _oldHref = oldHref;
            oldHref = newHref;
            hashChange.call(window, {
                'type': 'hashchange',
                'newURL': newHref,
                'oldURL': _oldHref
            });
        }
    }, 100);
} else if (window.addEventListener) {
    window.addEventListener("hashchange", hashChange, false);
}
else if (window.attachEvent) {
    window.attachEvent("onhashchange", hashChange);    
}

注意:此代码对于一个 hashchange 事件 很有用。如果您想要添加 多个 hashchange 处理程序,请使用以下方法。
它定义了两个函数,addHashChangeremoveHashChange。这两个方法都以一个函数作为参数。
(function() {
    if ('onhashchange' in window) {
        if (window.addEventListener) {
            window.addHashChange = function(func, before) {
                window.addEventListener('hashchange', func, before);
            };
            window.removeHashChange = function(func) {
                window.removeEventListener('hashchange', func);
            };
            return;
        } else if (window.attachEvent) {
            window.addHashChange = function(func) {
                window.attachEvent('onhashchange', func);
            };
            window.removeHashChange = function(func) {
                window.detachEvent('onhashchange', func);
            };
            return;
        }
    }
    var hashChangeFuncs = [];
    var oldHref = location.href;
    window.addHashChange = function(func, before) {
        if (typeof func === 'function')
            hashChangeFuncs[before?'unshift':'push'](func);
    };
    window.removeHashChange = function(func) {
        for (var i=hashChangeFuncs.length-1; i>=0; i--)
            if (hashChangeFuncs[i] === func)
                hashChangeFuncs.splice(i, 1);
    };
    setInterval(function() {
        var newHref = location.href;
        if (oldHref !== newHref) {
            var _oldHref = oldHref;
            oldHref = newHref;
            for (var i=0; i<hashChangeFuncs.length; i++) {
                hashChangeFuncs[i].call(window, {
                    'type': 'hashchange',
                    'newURL': newHref,
                    'oldURL': _oldHref
                });
            }
        }
    }, 100);
})();
// Usage, infinitely many times:
addHashChange(function(e){alert(e.newURL||location.href);});

2
事件监听器现在已正确绑定,但在IE7中不会执行任何操作,因为它不受支持。然而,IE8支持hashchange事件。对于IE7,您必须通过setInterval检测哈希更改。 - Rob W
1
@RobW 做得很好,但是在调用 hashChange 后,难道不应该使用 oldHref = newHref 吗? - Oriol
@RobG 为什么你要使用 _oldHref?直接用 oldHref 调用 hashChange,然后再更新 oldHref 不就可以了吗? - Oriol
1
假设hashChange函数抛出错误。那么oldHref永远不会被重置,并且该函数会一遍又一遍地被调用。为了避免这个问题,我在使用它之前将其存储在本地变量中。 - Rob W
1
@IanLunn 这些 [add|remove]HashChange 函数提供了一个抽象层来绑定 hashchange 事件。hashChangeFuncs 是已注册回调函数的列表,在哈希值改变时被调用。 - Rob W
显示剩余10条评论

3

attachEvent有两个参数:

bSuccess = object.attachEvent(sEvent, fpNotify)

这对所有低于IE9版本的IE都是必需的! :( 请参阅MDN参考。这可能有效:
if(window.addEventListener) {
    window.addEventListener("hashchange", hashChange, false);
}
else if (window.attachEvent) {
    window.attachEvent("onhashchange", hashchange);//SEE HERE...
    //missed the on. Fixed thanks to @Robs answer.
}

当然,如果可能的话,你应该直接使用JQuery,因为它封装了所有这些内容。同时,总是有一个插件可用: http://benalman.com/projects/jquery-hashchange-plugin/

2
太好了,感谢你的提示。问题:即使在IE7 JS调试模式下,我也没有从函数本身中获得任何错误(仅在我将其条件化之前的“addEventListener”)。有其他调试建议吗?我尝试了你的代码,但仍然不行……令人沮丧的是,也没有错误 :/ - Brian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接