573

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

有没有办法检查window.location.hash更改是否像这样?

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

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

但是如果我有基于#hash 的导航,当我按下浏览器上的后退按钮时它不起作用(所以我从 blah#456 跳转到 blah#123)。

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

4

13 回答 13

626

真正做到这一点的唯一方法(以及“真正简单的历史”如何做到这一点)是通过设置一个持续检查当前哈希的间隔,并将其与之前的哈希值进行比较,我们这样做并让订阅者订阅更改的如果哈希更改,我们将触发的事件.. 它并不完美,但浏览器本身并不支持此事件。


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

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

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

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

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

在此设置代码中,您可以检查本机浏览器支持,如果浏览器没有本机实现这一点,您可以设置一个计时器来轮询更改,并触发 jQuery 事件。

这完全使您的代码无需了解此支持问题,这种特殊事件的实现是微不足道的(获得一个简单的 98% 工作版本),但是当其他人已经有了.

于 2009-03-25T09:38:14.070 回答
300

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

  • 互联网浏览器 8
  • 火狐 3.6
  • 铬 5
  • 野生动物园 5
  • 歌剧 10.6
于 2009-03-25T10:33:46.043 回答
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/

于 2011-06-28T15:42:41.777 回答
14

IE浏览器中处理History和window.location.hash有很多技巧:

  • 正如原始问题所说,如果您从页面 a.html#b 转到 a.html#c,然后单击后退按钮,浏览器不知道该页面已更改。让我举个例子:window.location.href 将是 'a.html#c',无论你是在 a.html#b 还是 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 历史记录对某人有用。

于 2009-10-30T00:19:09.817 回答
12

Firefox 从 3.6 开始就有 onhashchange 事件。请参阅window.onhashchange

于 2010-06-24T17:29:30.410 回答
11

Ben Alman 有一个很棒的 jQuery 插件来处理这个问题:http: //benalman.com/projects/jquery-hashchange-plugin/

如果你不使用 jQuery,它可能是一个有趣的 dissect 参考。

于 2010-10-19T17:46:29.727 回答
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;

当然,这会触发你的观察者功能。

于 2010-10-29T09:04:18.900 回答
9

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

我观看了哈希参数使用

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

然后

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

工作得很好,可以使用前进和后退浏览器按钮以及浏览器历史记录。

于 2017-12-07T14:36:04.380 回答
6

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

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

于 2009-03-25T09:31:58.407 回答
1

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

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

于 2010-08-28T17:00:33.050 回答
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);

就是这样......现在,无论何时您点击后退或前进按钮,页面都会根据新的哈希值重新加载。

于 2011-02-25T02:40:16.163 回答
1

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

path.js NPM

路径.js GitHub

于 2015-01-02T22:23:11.933 回答
0

我使用了一个 jQuery 插件HUtil,并在其上编写了一个类似YUI History 的界面。

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

于 2009-12-28T17:25:55.300 回答