如何检查URL是否在JavaScript中发生了变化?例如,像GitHub这样使用AJAX的网站,会在#符号后附加页面信息,以创建唯一的URL,而无需重新加载页面。检测该URL是否发生变化的最佳方法是什么?

是否再次调用onload事件? 是否有URL的事件处理程序? 或者必须每秒钟检查URL以检测更改?


当前回答

看看jQuery的卸载函数。它能处理所有的事情。

https://api.jquery.com/unload/

当用户导航离开页面时,卸载事件被发送到窗口元素。这可能意味着许多事情之一。用户可以点击一个链接离开页面,或者在地址栏中输入一个新的URL。前进和后退按钮将触发事件。关闭浏览器窗口将触发该事件。即使是重新加载页面也会首先创建卸载事件。

$(window).unload(
    function(event) {
        alert("navigating");
    }
);

其他回答

我希望能够添加locationchange事件监听器。经过下面的修改,我们就可以这样做了

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

相比之下,window.addEventListener('hashchange',() =>{})只会在url中标签后的部分发生变化时触发,而window.addEventListener('popstate',() =>{})并不总是工作。

这种修改类似于Christian的回答,修改了history对象以添加一些功能。

默认情况下,在这些修改之前,有一个popstate事件,但是没有pushstate和replacestate事件。

这将修改这三个函数,以便所有函数都触发一个自定义locationchange事件供您使用,如果您想使用这些事件,还可以推送state和replacestate事件。

这些是修改:

(() => {
    let oldPushState = history.pushState;
    history.pushState = function pushState() {
        let ret = oldPushState.apply(this, arguments);
        window.dispatchEvent(new Event('pushstate'));
        window.dispatchEvent(new Event('locationchange'));
        return ret;
    };

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

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

注意,我们正在创建一个闭包,将旧函数保存为新函数的一部分,以便在调用新函数时调用它。

看看jQuery的卸载函数。它能处理所有的事情。

https://api.jquery.com/unload/

当用户导航离开页面时,卸载事件被发送到窗口元素。这可能意味着许多事情之一。用户可以点击一个链接离开页面,或者在地址栏中输入一个新的URL。前进和后退按钮将触发事件。关闭浏览器窗口将触发该事件。即使是重新加载页面也会首先创建卸载事件。

$(window).unload(
    function(event) {
        alert("navigating");
    }
);
window.onhashchange = function() { 
     //code  
}

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

or

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

window.addEventListener('popstate', function() { 
  //code  
});

与jQuery

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

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

在一个单独的线程中找到了一个工作答案:

没有一个事件是永远有效的,对于大多数大型spa来说,monkey patch pushState事件是非常偶然的。

所以聪明的投票对我来说是最有效的。您可以添加任意多的事件类型,但这些似乎对我来说做得很好。

为TS编写,但很容易修改:

const locationChangeEventType = "MY_APP-location-change";

// called on creation and every url change
export function observeUrlChanges(cb: (loc: Location) => any) {
  assertLocationChangeObserver();
  window.addEventListener(locationChangeEventType, () => cb(window.location));
  cb(window.location);
}

function assertLocationChangeObserver() {
  const state = window as any as { MY_APP_locationWatchSetup: any };
  if (state.MY_APP_locationWatchSetup) { return; }
  state.MY_APP_locationWatchSetup = true;

  let lastHref = location.href;

  ["popstate", "click", "keydown", "keyup", "touchstart", "touchend"].forEach((eventType) => {
    window.addEventListener(eventType, () => {
      requestAnimationFrame(() => {
        const currentHref = location.href;
        if (currentHref !== lastHref) {
          lastHref = currentHref;
          window.dispatchEvent(new Event(locationChangeEventType));
        }
      })
    })
  });
}

使用

observeUrlChanges((loc) => {
  console.log(loc.href)
})

这个解决方案对我很有效:

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

var oldURL = window.location.href;
setInterval(checkURLchange, 1000);