繁体   English   中英

如何检测位置 hash 的变化?

[英]How can I detect changes in location hash?

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

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

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

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

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

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

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


更新以保持此答案新鲜:

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

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

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

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

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

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

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

  • 浏览器 8
  • 火狐 3.6
  • 铬 5
  • 野生动物园 5
  • 歌剧 10.6

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

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

  • 正如最初的问题所说,如果您从页面 a.html#b 转到 a.html#c,然后点击后退按钮,浏览器不知道该页面已更改。 让我举个例子:window.location.href 将是'a.html#c',无论你是在a.html#b 还是a.html#c。

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

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

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

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

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

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

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

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

Firefox 有自己的实现来观察 object 的变化,但是如果你使用一些其他的实现(比如在 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;

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

我在 React 应用程序中使用它来使 URL 显示不同的参数,具体取决于用户所在的视图。

我观看了哈希参数使用

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

然后

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

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

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

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

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

路径.js NPM

路径.js GitHub

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

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

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);

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

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

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

简短的示例单击按钮进行更改 hash

 window.onhashchange = () => console.log(`Hash changed -> ${window.location.hash}`)
 <button onclick="window.location.hash=Math.random()">hash to Math.Random</button> <button onclick="window.location.hash='ABC'">Hash to ABC</button> <button onclick="window.location.hash='XYZ'">Hash to XYZ</button>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM