JavaScriptでURLが変更されたかどうかを確認するにはどうすればよいですか?たとえば、AJAXを使用するGitHubのようなWebサイトは、#記号の後にページ情報を追加して、ページをリロードせずに一意のURLを作成します。このURLが変更されたかどうかを検出する最良の方法は何ですか?
- される
onload
イベントが再び呼ばれますか? - URLのイベントハンドラーはありますか?
- または、変更を検出するためにURLを毎秒チェックする必要がありますか?
JavaScriptでURLが変更されたかどうかを確認するにはどうすればよいですか?たとえば、AJAXを使用するGitHubのようなWebサイトは、#記号の後にページ情報を追加して、ページをリロードせずに一意のURLを作成します。このURLが変更されたかどうかを検出する最良の方法は何ですか?
onload
イベントが再び呼ばれますか?回答:
最新のブラウザ(IE8 +、FF3.6 +、Chrome)では、でhashchange
イベントを聞くだけwindow
です。
一部の古いブラウザでは、継続的にチェックするタイマーが必要location.hash
です。jQueryを使用している場合は、まさにそれを行うプラグインがあります。
beforeunload
イベントのみが表示されます。コードがURLの変更を開始した場合、それが最もよくわかります。
locationchange
イベントリスナーを追加できるようにしたいと思いました。以下の変更後、次のようにできるようになります
window.addEventListener('locationchange', function(){
console.log('location changed!');
})
対照的window.addEventListener('hashchange',()=>{})
に、URLのハッシュタグの後の部分が変更された場合にのみ起動し、window.addEventListener('popstate',()=>{})
常に機能するとは限りません。
この修正は、クリスチャンの答えに似ていますに、いくつかの機能を追加するために履歴オブジェクトを変更します。
デフォルトでpopstate
は、イベントはありますが、、、pushstate
およびのイベントはありませんreplacestate
。
この修正これらの三つの機能すべての火災のカスタムようにlocationchange
も、あなたが使用するイベント、およびpushstate
およびreplacestate
イベントあなたがそれらを使用したい場合は:
/* 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'))
});
このコードを使用
window.onhashchange = function() {
//code
}
jQuery
$(window).bind('hashchange', function() {
//code
});
少し調べてから編集:
どういうわけか、私はMozillaのドキュメントにあるドキュメントにだまされているようです。popstate
イベント(およびそのコールバック関数がonpopstate
)されているトリガされないときはいつでもpushState()
、またはreplaceState()
コードで呼び出されます。したがって、元の答えはすべての場合に適用されるわけではありません。
ただし、@ alpha123に従って関数をモンキーパッチすることでこれを回避する方法があります。
var pushState = history.pushState;
history.pushState = function () {
pushState.apply(history, arguments);
fireEvents('pushState', arguments); // Some event-handling function
};
元の答え
この質問のタイトルが「URLの変更を検出する方法」であるとすると、(ハッシュアンカーだけでなく)完全なパスがいつ変更されるかを知りたい場合は、popstate
イベントをリッスンできます。
window.onpopstate = function(event) {
console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
};
現在(2017年1月)、世界中のブラウザの92%からpopstateがサポートされています。
jquery(およびプラグイン)を使用すると、次のことができます
$(window).bind('hashchange', function() {
/* things */
});
http://benalman.com/projects/jquery-hashchange-plugin/
そうでない場合は、yes、setIntervalを使用して、ハッシュイベント(window.location.hash)の変更を確認する必要があります。
更新!簡単なドラフト
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();
window.addEventListener("hashchange", hashChanged);
detect()
関数の実行で忙しすぎませんか?
ハッシュ変更イベントリスナーを追加します。
window.addEventListener('hashchange', function(e){console.log('hash changed')});
または、すべてのURL変更をリッスンするには:
window.addEventListener('popstate', function(e){console.log('url changed')});
window.onhashchangeには1つしか存在できず、他の誰かのコードを上書きする可能性があるため、これは以下のコードのようなものよりも優れています。
// Bad code example
window.onhashchange = function() {
// Code that overwrites whatever was previously in window.onhashchange
}
この解決策は私にとってうまくいきました:
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();
setInterval
にsetTimeout
:「それはcheckURLchange()秒ごとに新しいコールが作成されますので、しばらく後に停止するようにブラウザをもたらすのsetInterval()を使用したsetTimeout()一度しか呼び出されないため、正しい解決策です。」
setTimeout
、@ divibisanが提案するように使用する代わりにsetInterval
、関数の外側を移動します。checkURLchange();
また、オプションになります。
古い質問ですが、ロケーションバープロジェクトは非常に便利です。
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});
URLの変更をリッスンするには、以下を参照してください:
window.onpopstate = function(event) {
console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
};
特定の条件の後でリスナーを停止/削除する場合は、このスタイルを使用します。
window.addEventListener('popstate', function(e) {
console.log('url changed')
});
少しChromeの拡張を行っているときに、追加の問題で同じ問題に直面しました。時々、ページは変更されますがURLは変更されません。
たとえば、Facebookのホームページに移動し、[ホーム]ボタンをクリックします。ページを再読み込みしますが、URLは変更されません(1ページのアプリスタイル)。
99%の確率で、Angular、React、Vueなどのフレームワークからこれらのイベントを取得できるようにWebサイトを開発しています。
しかし、私のChrome拡張機能(バニラJSの場合)では、「ページの変更」ごとにトリガーされるイベントをリッスンする必要がありました。これは、通常、URLの変更によってキャッチできますが、そうでない場合もあります。
私の自家製の解決策は次のとおりでした:
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);
}
つまり、基本的にはウィンドウ履歴に適用されるleoneckertソリューションであり、単一ページアプリでページが変更されると変更されます。
ロケット科学ではありませんが、ここでは整数の等価性のみをチェックし、より大きなオブジェクトやDOM全体ではないことを考えると、私が見つけた最もクリーンなソリューションです。
window.history
最大長は50です(少なくともChrome 80以降)。それ以降はwindow.history.length
常に50を返します。その場合、このメソッドは変更を認識できません。
jQuery unload関数を見てください。それはすべてのものを処理します。
https://api.jquery.com/unload/
アンロードイベントは、ユーザーがページから移動したときにウィンドウ要素に送信されます。これは、多くのことの1つを意味する可能性があります。ユーザーはリンクをクリックしてページを離れるか、アドレスバーに新しいURLを入力した可能性があります。進むボタンと戻るボタンでイベントがトリガーされます。ブラウザーウィンドウを閉じると、イベントがトリガーされます。ページのリロードでも、最初にアンロードイベントが作成されます。
$(window).unload(
function(event) {
alert("navigating");
}
);
以下の答えはここから来ます(古いjavascript構文(矢印機能なし、IE 10+をサポート)):https : //stackoverflow.com/a/52809105/9168962
(function() {
if (typeof window.CustomEvent === "function") return false; // If not IE
function CustomEvent(event, params) {
params = params || {bubbles: false, cancelable: false, detail: null};
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
window.CustomEvent = CustomEvent;
})();
(function() {
history.pushState = function (f) {
return function pushState() {
var ret = f.apply(this, arguments);
window.dispatchEvent(new CustomEvent("pushState"));
window.dispatchEvent(new CustomEvent("locationchange"));
return ret;
};
}(history.pushState);
history.replaceState = function (f) {
return function replaceState() {
var ret = f.apply(this, arguments);
window.dispatchEvent(new CustomEvent("replaceState"));
window.dispatchEvent(new CustomEvent("locationchange"));
return ret;
};
}(history.replaceState);
window.addEventListener("popstate", function() {
window.dispatchEvent(new CustomEvent("locationchange"));
});
})();
setInterval
以前の通話をキャンセルせずに、通話ごとに新しい通話を開始している-おそらく、setTimeout