【问题标题】:How can I detect changes in location hash?如何检测位置哈希的变化?
【发布时间】:2010-10-15 09:53:31
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 查看这个 jquery 插件:github.com/cowboy/jquery-hashchange
  • History.js 支持 HTML5 状态管理功能(因此您不再需要使用哈希!)并使用 hashchanges 优雅地将其降级​​为 HTML4 浏览器。它支持开箱即用的 jQuery、MooTools 和 Prototype。
  • @balupton,实际上我们仍然需要使用散列来向用户提供“新页面”已插入其历史记录的反馈,除非您使用 URL 更改作为反馈。
  • 嗯...我觉得你需要 moar jQuery

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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


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

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

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

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

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

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

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

    【讨论】:

    • 最新的 Firefox 版本(3.6 alpha)现在也支持原生哈希更改事件:developer.mozilla.org/en/DOM/window.onhashchange 这个事件当然值得检查,但请注意,IE8 会告诉您该事件存在时它在 IE7 兼容模式下运行.. 遗憾的是事件没有触发.. 您需要检查事件并且浏览器似乎不是 IE7.. 叹息(或尝试使用 IE 触发事件fireEvent 方法)。
    • 在撰写本文时,WebKit 还会触发 hashchange 事件,而 Safari(稳定版)还没有。
    • 只是为了添加另一个更新,hashchange 事件现已得到广泛支持:caniuse.com/#search=hash
    • 我是唯一一个认为不请自来的 jQuery 答案很痛苦的人吗?
    • 此答案现已弃用
    【解决方案3】:

    HTML5 specifies a hashchange event。这个事件现在是supported by all modern browsers。在以下浏览器版本中添加了支持:

    • Internet Explorer 8
    • 火狐3.6
    • 铬 5
    • Safari 5
    • Opera 10.6

    【讨论】:

    • 更新:FF 5、Safari 5 和 Chrome 12 自 2011 年 6 月起支持此事件。
    • 这里是CanIUse page for hashchange。这是hashchange on quirksmode。 IE 支持在区分大小写方面存在问题。
    • @everybody,无需在 cmets 部分继续附加答案——这就是“编辑”按钮的用途。 :)
    • 用法:window.onhashchange = function() { doYourStuff(); }
    • hashchange event 的 MDN 文档。
    【解决方案4】:

    在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 存储在历史记录中只有如果元素 '' 和 '' 以前存在于页面中。

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

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

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

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

            【讨论】:

            • Ben Alman 插件似乎不再维护。不过有很多叉子。
            【解决方案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;
            

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

            【讨论】:

            • 更好的使用:window.location.href 而不是 window.location。
            • 他在看window.location.hash,而不是window.location。
            • @BrianMortenson:根据文档 (developer.mozilla.org/en-US/docs/JavaScript/Reference/…),您必须将 watch 应用于拥有正在更改的属性并且您想要观察它的对象。
            • @gion_13 是的,这正是我想要指出的。我说的“他”是指你,它是针对欧文努斯的评论。我应该更清楚。感谢您的澄清评论。
            【解决方案10】:
            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】:

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

              【讨论】:

                【解决方案12】:

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

                path.js NPM

                path.js GitHub

                【讨论】:

                  【解决方案13】:

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

                  我使用

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

                  然后

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

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

                  【讨论】:

                  • 在您的addEventListener 通话中,您应该从doSomethingWithChangeFunction 中删除()
                  • 您能提供删除 () 的原因吗?我知道它适用于任何一种,而且更少的代码通常是更好的选择,但这似乎很挑剔,除非有充分的理由支持它?
                  • ?它不应该与() 一起使用。 addEventListener 函数要求您传入一个函数。 doSomethingWithChangeFunction 是一个函数。 doSomethingWithChangeFunction() 是该函数的返回值,在这种情况下它不是函数。
                  猜你喜欢
                  • 1970-01-01
                  • 2021-11-19
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-10-19
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多