ある時点で変更するサイトのGreasemonkeyスクリプトを書いていlocation.href
ます。
ページが変更されたwindow.addEventListener
ときに(または同様の方法で)イベントを取得するにはどうすればよいwindow.location.href
ですか?また、新しい/変更されたURLを指すドキュメントのDOMにアクセスする必要があります。
タイムアウトとポーリングを含む他の解決策を見てきましたが、可能であればそれを避けたいと思います。
回答:
popstateイベントは、アクティブな履歴エントリが変更されたときに発生します。[...] popstateイベントは、戻るボタンをクリックする(またはJavaScriptでhistory.back()を呼び出す)などのブラウザーアクションを実行することによってのみトリガーされます。
したがって、使用時にpopstate
イベントをリッスンしてイベントを送信するだけで、変更に対してアクションを実行できます。popstate
history.pushState()
href
window.addEventListener('popstate', listener);
const pushUrl = (href) => {
history.pushState({}, '', href);
window.dispatchEvent(new Event('popstate'));
};
pushState
私は自分の拡張機能「GrabAnyMedia」でこのスクリプトを使用し、正常に動作します(youtubeケースのように)
var oldHref = document.location.href;
window.onload = function() {
var
bodyList = document.querySelector("body")
,observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (oldHref != document.location.href) {
oldHref = document.location.href;
/* Changed ! your code here */
}
});
});
var config = {
childList: true,
subtree: true
};
observer.observe(bodyList, config);
};
window.addEventListener("load", () => {})
ただし、window.onloadの代わりに使用します:)
ポーリングを回避することはできません。hrefの変更に関するイベントはありません。
船外に出なければ、とにかくインターバルの使用はかなり軽いです。約50ミリ秒ごとにhrefをチェックしても、心配している場合はパフォーマンスに大きな影響はありません。
popstate
とのこれらの新しいソリューションがありhashchange
ます。
onhashchange
使用できる
デフォルトのイベントがあります。
そして、このように使用することができます:
function locationHashChanged( e ) {
console.log( location.hash );
console.log( e.oldURL, e.newURL );
if ( location.hash === "#pageX" ) {
pageX();
}
}
window.onhashchange = locationHashChanged;
ブラウザがサポートしておらずoldURL
、newURL
次のようにバインドできる場合:
//let this snippet run before your hashChange event binding code
if( !window.HashChangeEvent )( function() {
let lastURL = document.URL;
window.addEventListener( "hashchange", function( event ) {
Object.defineProperty( event, "oldURL", { enumerable: true, configurable: true, value: lastURL } );
Object.defineProperty( event, "newURL", { enumerable: true, configurable: true, value: document.URL } );
lastURL = document.URL;
} );
} () );
beforeUnloadを試しましたか?このイベントは、ページがナビゲーションリクエストに応答する直前に発生します。これには、hrefの変更が含まれている必要があります。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE></TITLE>
<META NAME="Generator" CONTENT="TextPad 4.6">
<META NAME="Author" CONTENT="?">
<META NAME="Keywords" CONTENT="?">
<META NAME="Description" CONTENT="?">
</HEAD>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
$(window).unload(
function(event) {
alert("navigating");
}
);
$("#theButton").click(
function(event){
alert("Starting navigation");
window.location.href = "http://www.bbc.co.uk";
}
);
});
</script>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
<button id="theButton">Click to navigate</button>
<a href="http://www.google.co.uk"> Google</a>
</BODY>
</HTML>
ただし、スクリプトが原因であるか、誰かがリンクをクリックしたことが原因であるかどうかに関係なく、ページから移動するたびにイベントが発生することに注意してください。あなたの本当の課題は、イベントが発生するさまざまな理由を検出することです。(これがロジックにとって重要な場合)
hash
状況を考慮しなかった-それについて考えるだろう。新しいDOMにアクセスできることに関しては、新しいDOMがロードされる前にイベントが発生するため、(イベントハンドラーからこれにアクセスする限り)運が悪いことになります。新しいページのonloadイベントにロジックを組み込むことはできるかもしれませんが、そのページのすべてのロードに対してロジックを実行する必要があるかどうかの識別に関して同じ問題が発生する可能性があります。ページフローなど、達成しようとしていることについてもう少し詳しく教えてください。
jQueryの、ちょうどしてみてください
$(window).on('beforeunload', function () {
//your code goes here on location change
});
javascriptを使用して:
window.addEventListener("beforeunload", function (event) {
//your code goes here on location change
});
ドキュメントを参照してください:https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
を変更するには2つの方法がありますlocation.href
。location.href = "y.html"
ページをリロードする書き込み、またはページをリロードしない履歴APIを使用できます。最近、最初の実験をたくさんしました。
子ウィンドウを開き、親ウィンドウから子ページの負荷をキャプチャすると、ブラウザが異なれば動作も大きく異なります。一般的なのは、古いドキュメントを削除して新しいドキュメントを追加することだけです。たとえば、readystatechangeやloadイベントハンドラーを古いドキュメントに追加しても効果はありません。ほとんどのブラウザはウィンドウオブジェクトからもイベントハンドラを削除しますが、唯一の例外はFirefoxです。Chrome with Karma runnerおよびFirefoxでは、次の場合、loadingreadyStateで新しいドキュメントをキャプチャできます。unload + next tick
。したがって、たとえば、loadイベントハンドラーまたはreadystatechangeイベントハンドラーを追加したり、ブラウザーが新しいURIでページをロードしていることをログに記録したりできます。手動テストを使用するChrome(おそらくGreaseMonkeyも)およびOpera、PhantomJS、IE10、IE11では、読み込み状態で新しいドキュメントをキャプチャすることはできません。これらのブラウザunload + next tick
では、ページのロードイベントが発生する数百ミリ秒後にコールバックがコールバックを呼び出します。遅延は通常100〜300ミリ秒ですが、オペラsimetimeでは次のティックに750ミリ秒の遅延が発生するため、怖いです。したがって、すべてのブラウザで一貫した結果が必要な場合は、loadイベントの後でやりたいことを実行しますが、その前に場所が上書きされないという保証はありません。
var uuid = "win." + Math.random();
var timeOrigin = new Date();
var win = window.open("about:blank", uuid, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes");
var callBacks = [];
var uglyHax = function (){
var done = function (){
uglyHax();
callBacks.forEach(function (cb){
cb();
});
};
win.addEventListener("unload", function unloadListener(){
win.removeEventListener("unload", unloadListener); // Firefox remembers, other browsers don't
setTimeout(function (){
// IE10, IE11, Opera, PhantomJS, Chrome has a complete new document at this point
// Chrome on Karma, Firefox has a loading new document at this point
win.document.readyState; // IE10 and IE11 sometimes fails if I don't access it twice, idk. how or why
if (win.document.readyState === "complete")
done();
else
win.addEventListener("load", function (){
setTimeout(done, 0);
});
}, 0);
});
};
uglyHax();
callBacks.push(function (){
console.log("cb", win.location.href, win.document.readyState);
if (win.location.href !== "http://localhost:4444/y.html")
win.location.href = "http://localhost:4444/y.html";
else
console.log("done");
});
win.location.href = "http://localhost:4444/x.html";
Firefoxでのみスクリプトを実行する場合は、簡略化されたバージョンを使用して、読み込み状態でドキュメントをキャプチャできます。たとえば、読み込み済みページのスクリプトは、URIの変更をログに記録する前に移動できません。
var uuid = "win." + Math.random();
var timeOrigin = new Date();
var win = window.open("about:blank", uuid, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes");
var callBacks = [];
win.addEventListener("unload", function unloadListener(){
setTimeout(function (){
callBacks.forEach(function (cb){
cb();
});
}, 0);
});
callBacks.push(function (){
console.log("cb", win.location.href, win.document.readyState);
// be aware that the page is in loading readyState,
// so if you rewrite the location here, the actual page will be never loaded, just the new one
if (win.location.href !== "http://localhost:4444/y.html")
win.location.href = "http://localhost:4444/y.html";
else
console.log("done");
});
win.location.href = "http://localhost:4444/x.html";
URIのハッシュ部分を変更する、または履歴APIを使用するシングルページアプリケーションについて話している場合は、ウィンドウのイベントhashchange
とpopstate
イベントをそれぞれ使用できます。同じページにとどまるまで履歴を前後に移動しても、それらをキャプチャできます。ドキュメントはそれらによって変更されず、ページは実際には再ロードされません。