On - window.location.hash - 更改?

时间:2009-03-25 09:10:19

标签: javascript ajax javascript-events fragment-identifier hashchange

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

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

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

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

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

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

13 个答案:

答案 0 :(得分:603)

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


更新以保持这个答案新鲜:

如果你正在使用jQuery(今天应该对大多数人来说有点基础)那么一个很好的解决方案就是使用jQuery为你提供的抽象,使用它的事件系统来监听window对象上的hashchange事件。

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

这里的好处是你可以编写代码,甚至不需要担心hashchange支持,但是你需要做一些魔术,以一种鲜为人知的jQuery特性jQuery special events的形式。

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

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

这完全解除了你的代码需要理解这个支持问题,这种特殊事件的实现是微不足道的(获得一个简单的98%工作版本),但为什么这样做when somebody else has already

答案 1 :(得分:282)

HTML5 specifies a hashchange event。此活动现在为supported by all modern browsers。在以下浏览器版本中添加了支持:

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

答案 2 :(得分:50)

请注意,对于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/

答案 3 :(得分: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.html#b和a.html#c仅存储在历史记录和'< a name =“#c”>'以前存在于页面中。

  • 但是,如果您在页面中放置iframe,请在该iframe中从a.html#b导航到a.html#c,然后点击后退按钮,iframe.contentWindow.document.location.href更改正如所料。

  • 如果您在代码中使用'document.domain = 某些',则无法访问iframe.contentWindow.document.open()'(许多历史记录管理器都会那)

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

答案 4 :(得分:12)

自3.6以来,Firefox已经发生了一次onhashchange事件。请参阅 window.onhashchange

答案 5 :(得分:11)

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

如果您不使用jQuery,它可能是一个有趣的解剖参考。

答案 6 :(得分:9)

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

Firefox有own implementation for watching changes of object,但是如果你使用其他一些实现(例如 Watch for object properties changes in 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;

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

答案 7 :(得分:6)

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

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

答案 8 :(得分:6)

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

我使用

观看了哈希参数
window.addEventListener('hashchange', doSomethingWithChangeFunction());

然后

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

使用前进和后退浏览器按钮以及浏览器历史记录。

答案 9 :(得分:1)

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

另一个值得注意的项目是jQuery Ajaxy,它几​​乎是jQuery History的一个扩展,可以添加ajax。当你开始使用带有哈希的ajax时,它会得到quite complicated

答案 10 :(得分: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);

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

答案 11 :(得分:1)

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

path.js NPM

path.js GitHub

答案 12 :(得分:0)

我使用了jQuery插件HUtil,并在其上面编写了一个YUI历史记录界面。

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