开启-window.location.hash-更改了吗?


558

我正在使用Ajax和哈希进行导航。

有没有办法检查这种window.location.hash变化是否?

http://example.com/blah #123http://example.com/blah #456

如果我在加载文档时检查它,它将起作用。

但是,如果我具有基于#hash的导航,则在按浏览器上的“后退”按钮时将不起作用(因此,我从blah#456跳至blah#123)。

它显示在地址框中,但我无法用JavaScript捕获它。


6
签出这个jquery插件:github.com/cowboy/jquery-hashchange
Xavi

9
History.js支持HTML5状态管理功能(因此您不再需要使用哈希!),并使用hashchanges将其优雅地降级为HTML4浏览器。它开箱即用地支持jQuery,MooTools和Prototype。
balupton 2011年

@balupton,实际上,除非您使用URL更改作为反馈,否则实际上我们仍然需要使用哈希来向用户提供“新页面”已插入其历史的反馈。
Pacerier,2014年


嗯...我认为您需要摩尔jQuery
RaisingAgent

Answers:


616

真正做到这一点的唯一方法(以及“ reallysimplehistory”是如何做到的)是通过设置一个间隔来保持检查当前哈希值,并将其与之前的哈希值进行比较,然后执行此操作,并让订阅者订阅更改后的内容如果哈希发生变化,则触发该事件。它并不完美,但浏览器实际上并不原生支持此事件。


更新以使此答案保持最新:

如果您使用的是jQuery(今天对于大多数人来说应该是基础的),那么一个不错的解决方案是使用jQuery通过使用其事件系统侦听window对象上的hashchange事件为您提供的抽象。

$(window).on('hashchange', function() {
  //.. work ..
});

这里的好处是您可以编写甚至不需要担心hashchange支持的代码,但是您确实需要做一些魔术,以一种鲜为人知的jQuery特性jQuery特殊事件的形式

使用此功能,您基本上可以为任何事件运行一些设置代码,这是有人第一次尝试以任何方式使用该事件(例如绑定到事件)。

在此设置代码中,您可以检查是否支持本机浏览器,如果浏览器不是本机实现的,则可以设置单个计时器以轮询更改并触发jQuery事件。

这完全不需要您理解此支持问题的代码,这种特殊事件的实现很简单(获得简单的98%工作版本),但是当别人已经这样做为什么要这样做。


7
IE8可以。更多内容
谢尔盖·伊林斯基

28
最新的Firefox版本(3.6 alpha)现在还支持本地哈希更改事件:developer.mozilla.org/en/DOM/window.onhashchange 当然值得对此事件进行检查,但是请注意IE8会告诉您该事件在IE7兼容模式下运行时存在。.可悲的是,该事件不会触发..您需要检查该事件,并且浏览器似乎不是IE7。.叹气(或尝试触发该事件IE的fireEvent方法)。
Meandmycode

8
在撰写本文时,WebKit也会触发hashchange事件,而Safari(稳定)尚未触发。
jholster 2010年

51
只是添加了另一个更新,该hashchange事件现在得到了广泛支持:caniuse.com/#search=hash
Paystey 2012年

19
我是唯一认为未经请求的jQuery答案很痛苦的人吗?
卢克

290

HTML5 指定一个hashchange事件所有现代浏览器现在都支持此事件。在以下浏览器版本中添加了支持:

  • Internet Explorer 8
  • Firefox 3.6
  • 铬5
  • Safari 5
  • Opera 10.6

20
更新:截至2011
。– james.garriss

2
这是用于hashchangeCanIUse页面。这是quirksmode上的hashchange。IE支持在区分大小写方面存在漏洞。
东武

3
@每个人,无需继续在评论部分中添加答案-这就是“编辑”按钮的作用。:)
Michael Martin-Smucker 2012年

15
用法:window.onhashchange = function() { doYourStuff(); }
克里斯(Chris)

4

52

请注意,在Internet Explorer 7和Internet Explorer 9的情况下,该if语句将为true(对于Windows中的“ onhashchange”),但该声明window.onhashchange永远不会触发,因此最好存储哈希值,并每隔100毫秒检查一次它是否被更改适用于所有版本的Internet Explorer。

    if (("onhashchange" in window) && !($.browser.msie)) {
         window.onhashchange = function () {
              alert(window.location.hash);
         }
         // Or $(window).bind( 'hashchange',function(e) {
         //       alert(window.location.hash);
         //   });
    }
    else {
        var prevHash = window.location.hash;
        window.setInterval(function () {
           if (window.location.hash != prevHash) {
              prevHash = window.location.hash;
              alert(window.location.hash);
           }
        }, 100);
    }

编辑-自jQuery 1.9起,$.browser.msie不支持。资料来源:http//api.jquery.com/jquery.browser/


14

在IE浏览器中,有许多技巧可以处理历史记录和window.location.hash:

  • 如原始问题所述,如果您从页面a.html#b转到a.html#c,然后单击“后退”按钮,浏览器将不知道该页面已更改。让我举个例子:无论您在a.html#b还是a.html#c中,window.location.href均为'a.html#c'。

  • 实际上,当页面中先前存在元素“ <a name="#b">”和“ <a name="#c">”时,a.html#b和a.html#c才会存储在历史记录中。

  • 但是,如果将iframe放在页面中,请从该iframe中的a.html#b导航到a.html#c,然后单击“后退”按钮,iframe.contentWindow.document.location.href会按预期更改。

  • 如果您在代码中使用“ document.domain = something ”,那么您将无法访问iframe.contentWindow.document.open()(许多历史记录管理器都这样做)

我知道这不是一个真正的回应,但也许IE历史记录记录对某些人有用。




9

您可以在“ window.location”对象的“ hash”属性上轻松实现观察者(“ watch”方法)。

Firefox有其自己的实现来监视对象的更改,但是如果您使用其他实现(例如,监视JavaScript中的对象属性的更改)-对于其他浏览器,就可以解决问题。

该代码将如下所示:

window.location.watch(
    'hash',
    function(id,oldVal,newVal){
        console.log("the window's hash value has changed from "+oldval+" to "+newVal);
    }
);

然后您可以对其进行测试:

var myHashLink = "home";
window.location = window.location + "#" + myHashLink;

当然,这将触发您的观察者功能。


更好地使用:window.location.href而不是window.location。
Codebeat 2012年

3
他在看window.location.hash,而不是window.location。
未定义

1
@BrianMortenson:根据文档(developer.mozilla.org/en-US/docs/JavaScript/Reference/…),您必须将其应用于watch拥有正在更改的属性的对象,并要观察它。
gion_13 2012年

@ gion_13是的,这正是我要指出的。“他”是指您,它是针对欧文努斯的。我应该更清楚了。感谢您的澄清评论。
2012年

7

我在React应用程序中使用它来使URL根据用户所在的视图显示不同的参数。

我看了使用

window.addEventListener('hashchange', doSomethingWithChangeFunction());

然后

doSomethingWithChangeFunction () { 
    // Get new hash value
    let urlParam = window.location.hash;
    // Do something with new hash value
};

做过款待,可以使用浏览器的前进和后退按钮以及浏览器历史记录。


1
addEventListener通话中,您应该()doSomethingWithChangeFunction
Jason S

您能否提供删除()的理由?我知道这两种方法都可以使用,并且更少的代码通常是更好的选择,但是这似乎很挑剔,除非有充分的理由进行备份?
Sprose

6
?它不应该与()。该addEventListener函数要求您传入一个函数。doSomethingWithChangeFunction是一个功能。doSomethingWithChangeFunction()是该函数的返回值,在这种情况下不是函数。
杰森S

6

可以在http://code.google.com/p/reallysimplehistory/中找到不错的实现。它具有的唯一(也是)问题和错误是:在Internet Explorer中,手动修改位置哈希将重置整个历史记录堆栈(这是浏览器问题,无法解决)。

请注意,Internet Explorer 8确实支持“ hashchange”事件,并且由于它已成为HTML5的一部分,因此您可能会期望其他浏览器跟上。


1

另一个不错的实现是jQuery History,如果浏览器支持它,它将使用本机onhashchange事件;否则,它将为浏览器使用适当的iframe或间隔,以确保成功模拟所有预期功能。它还提供了一个不错的接口来绑定到某些状态。

另一个值得注意的项目是jQuery Ajaxy,它几乎是jQuery History的扩展,可以将ajax添加到混合中。当您开始使用带有哈希值的ajax时,它变得相当复杂


1
var page_url = 'http://www.yoursite.com/'; // full path leading up to hash;
var current_url_w_hash = page_url + window.location.hash; // now you might have something like: http://www.yoursite.com/#123

function TrackHash() {
    if (document.location != page_url + current_url_w_hash) {
        window.location = document.location;
    }
    return false;
}
var RunTabs = setInterval(TrackHash, 200);

就这样...现在,只要您按下后退或前进按钮,页面就会根据新的哈希值重新加载。


不要使用评估字符串
Vitim.us 2013年

1

我一直在使用path.js进行客户端路由。我发现它非常简洁,轻巧(它也已经发布到NPM),并且利用了基于哈希的导航。

path.js NPM

path.js GitHub


0

我使用了一个jQuery插件HUtil,并在其顶部编写了一个类似UI 的YUI历史记录。

检查一次。如果您需要帮助,我可以提供帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.