如何检测在 JavaScript 中散列后 URL 是否已更改

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6390341/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:31:18  来源:igfitidea点击:

How to detect if URL has changed after hash in JavaScript

javascriptajax

提问by AJ00200

How can I check if a URL has changed in JavaScript? For example, websites like GitHub, which use AJAX, will append page information after a # symbol to create a unique URL without reloading the page. What is the best way to detect if this URL changes?

如何检查 JavaScript 中的 URL 是否已更改?例如,使用 AJAX 的 GitHub 等网站会在 # 符号后附加页面信息以创建唯一的 URL,而无需重新加载页面。检测此 URL 是否更改的最佳方法是什么?

  • Is the onloadevent called again?
  • Is there an event handler for the URL?
  • Or must the URL be checked every second to detect a change?
  • onload事件是否再次被调用?
  • URL 是否有事件处理程序?
  • 或者必须每秒检查 URL 以检测更改?

采纳答案by phihag

In modern browsers (IE8+, FF3.6+, Chrome), you can just listen to the hashchangeevent on window.

在现代浏览器(IE8+、FF3.6+、Chrome)中,您可以只hashchangewindow.

In some old browsers, you need a timer that continually checks location.hash. If you're using jQuery, there is a pluginthat does exactly that.

在一些旧浏览器中,您需要一个持续检查location.hash. 如果您使用的是 jQuery,那么有一个插件可以做到这一点。

回答by aljgom

I wanted to be able to add locationchangeevent listeners. After the modification below, we'll be able to do it, like this

我希望能够添加locationchange事件侦听器。下面修改后,我们就可以做到了,像这样

window.addEventListener('locationchange', function(){
    console.log('location changed!');
})

In contrast, window.addEventListener('hashchange',()=>{})would only fire if the part after a hashtag in a url changes, and window.addEventListener('popstate',()=>{})doesn't always work.

相比之下,window.addEventListener('hashchange',()=>{})只有在 url 中的主题标签之后的部分发生更改时才会触发,并且window.addEventListener('popstate',()=>{})并不总是有效。

This modification, similar to Christian's answer, modifies the history object to add some functionality.

此修改类似于Christian 的回答,修改历史对象以添加一些功能。

By default, there's a popstateevent, but there are no events for pushstate, and replacestate.

默认情况下,有一个popstate事件,但没有pushstate, 和 的事件replacestate

This modifies these three functions so that all fire a custom locationchangeevent for you to use, and also pushstateand replacestateevents if you want to use those:

这会修改这三个功能,使所有的消防自定义locationchange事件供您使用,也pushstatereplacestate活动,如果你想使用这些:

/* These are the modifications: */
history.pushState = ( f => function pushState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('pushstate'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.pushState);

history.replaceState = ( f => function replaceState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('replacestate'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.replaceState);

window.addEventListener('popstate',()=>{
    window.dispatchEvent(new Event('locationchange'))
});

回答by Behnam Mohammadi

use this code

使用此代码

window.onhashchange = function() { 
     //code  
}

with jQuery

使用 jQuery

$(window).bind('hashchange', function() {
     //code
});

回答by Cristian

EDIT after a bit of researching:

经过一番研究后编辑:

It somehow seems that I have been fooled by the documentation present on Mozilla docs. The popstateevent (and its callback function onpopstate) are not triggeredwhenever the pushState()or replaceState()are called in code. Therefore the original answer does not apply in all cases.

不知何故,我似乎被 Mozilla 文档中的文档所迷惑。每当在代码中调用或时,都不会触发popstate事件(及其回调函数onpopstate)。因此,原始答案并不适用于所有情况。pushState()replaceState()

However there is a way to circumvent this by monkey-patching the functions according to @alpha123:

但是,有一种方法可以通过根据 @alpha123 对函数进行猴子修补来规避此问题

var pushState = history.pushState;
history.pushState = function () {
    pushState.apply(history, arguments);
    fireEvents('pushState', arguments);  // Some event-handling function
};

Original answer

原答案

Given that the title of this question is "How to detect URL change" the answer, when you want to know when the full path changes (and not just the hash anchor), is that you can listen for the popstateevent:

鉴于此问题的标题是“如何检测 URL 更改”,当您想知道完整路径何时更改(而不仅仅是哈希锚点)时,答案是您可以侦听popstate事件:

window.onpopstate = function(event) {
  console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
};

Reference for popstate in Mozilla Docs

Mozilla Docs 中 popstate 的参考

Currently (Jan 2017) there is support for popstate from 92%of browsers worldwide.

目前(2017 年 1 月)全球92%的浏览器都支持 popstate

回答by Pantelis

With jquery (and a plug-in) you can do

使用 jquery(和插件)你可以做到

$(window).bind('hashchange', function() {
 /* things */
});

http://benalman.com/projects/jquery-hashchange-plugin/

http://benalman.com/projects/jquery-hashchange-plugin/

Otherwise yes, you would have to use setInterval and check for a change in the hash event (window.location.hash)

否则是的,您必须使用 setInterval 并检查哈希事件(window.location.hash)中的更改

Update! A simple draft

更新!一个简单的草稿

function hashHandler(){
    this.oldHash = window.location.hash;
    this.Check;

    var that = this;
    var detect = function(){
        if(that.oldHash!=window.location.hash){
            alert("HASH CHANGED - new has" + window.location.hash);
            that.oldHash = window.location.hash;
        }
    };
    this.Check = setInterval(function(){ detect() }, 100);
}

var hashDetection = new hashHandler();

回答by Trev14

Add a hash change event listener!

添加哈希更改事件侦听器!

window.addEventListener('hashchange', function(e){console.log('hash changed')});

Or, to listen to all URL changes:

或者,要侦听所有 URL 更改:

window.addEventListener('popstate', function(e){console.log('url changed')});

This is better than something like the code below because only one thing can exist in window.onhashchange and you'll possibly be overwriting someone else's code.

这比下面的代码要好,因为 window.onhashchange 中只能存在一件事,而且您可能会覆盖其他人的代码。

// Bad code example

window.onhashchange = function() { 
     // Code that overwrites whatever was previously in window.onhashchange  
}

回答by leoneckert

this solution worked for me:

这个解决方案对我有用:

var oldURL = "";
var currentURL = window.location.href;
function checkURLchange(currentURL){
    if(currentURL != oldURL){
        alert("url changed!");
        oldURL = currentURL;
    }

    oldURL = window.location.href;
    setInterval(function() {
        checkURLchange(window.location.href);
    }, 1000);
}

checkURLchange();

回答by Ray Booysen

Although an old question, the Location-barproject is very useful.

虽然是个老问题,但Location-bar项目非常有用。

var LocationBar = require("location-bar");
var locationBar = new LocationBar();

// listen to all changes to the location bar
locationBar.onChange(function (path) {
  console.log("the current url is", path);
});

// listen to a specific change to location bar
// e.g. Backbone builds on top of this method to implement
// it's simple parametrized Backbone.Router
locationBar.route(/some\-regex/, function () {
  // only called when the current url matches the regex
});

locationBar.start({
  pushState: true
});

// update the address bar and add a new entry in browsers history
locationBar.update("/some/url?param=123");

// update the address bar but don't add the entry in history
locationBar.update("/some/url", {replace: true});

// update the address bar and call the `change` callback
locationBar.update("/some/url", {trigger: true});

回答by codejockie

To listen to url changes, see below:

要收听 url 更改,请参见下文:

window.onpopstate = function(event) {
  console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
};

Use this style if you intend to stop/remove listener after some certain condition.

如果您打算在某些特定条件后停止/删除侦听器,请使用此样式。

window.addEventListener('popstate', function(e) {
   console.log('url changed')
});

回答by Alburkerk

While doing a little chrome extension, I faced the same problem with an additionnal problem : Sometimes, the page change but not the URL.

在做一些 chrome 扩展时,我遇到了同样的问题,还有一个额外的问题:有时,页面会更改,但 URL 不会更改。

For instance, just go to the Facebook Homepage, and click on the 'Home' button. You will reload the page but the URL won't change (one-page app style).

例如,只需转到 Facebook 主页,然后单击“主页”按钮。您将重新加载页面,但 URL 不会更改(单页应用程序样式)。

99% of the time, we are developping websites so we can get those events from Frameworks like Angular, React, Vue etc..

99% 的时间,我们都在开发网站,以便我们可以从 Angular、React、Vue 等框架中获取这些事件。

BUT, in my case of a Chrome extension (in Vanilla JS), I had to listen to an event that will trigger for each "page change", which can generally be caught by URL changed, but sometimes it doesn't.

但是,在我的 Chrome 扩展程序(在 Vanilla JS 中)的情况下,我必须监听一个会触发每个“页面更改”的事件,这通常可以通过 URL 更改来捕获,但有时不会。

My homemade solution was the following :

我自制的解决方案如下:

listen(window.history.length);
var oldLength = -1;
function listen(currentLength) {
  if (currentLength != oldLength) {
    // Do your stuff here
  }

  oldLength = window.history.length;
  setTimeout(function () {
    listen(window.history.length);
  }, 1000);
}

So basically the leoneckert solution, applied to window history, which will change when a page changes in a single page app.

所以基本上是 leoneckert 解决方案,应用于窗口历史记录,当单页应用程序中的页面更改时,它会更改。

Not rocket science, but cleanest solution I found, considering we are only checking an integer equality here, and not bigger objects or the whole DOM.

不是火箭科学,而是我找到的最干净的解决方案,考虑到我们在这里只检查整数相等,而不是更大的对象或整个 DOM。