Я пишу сценарий Greasemonkey для сайта, который в какой-то момент изменяется location.href
.
Как я могу получить событие (через window.addEventListener
или что-то подобное) при window.location.href
изменении на странице? Мне также нужен доступ к DOM документа, указывающего на новый / измененный URL-адрес.
Я видел другие решения, которые включают тайм-ауты и опрос, но я бы хотел избежать этого, если это возможно.
javascript
dom
greasemonkey
dom-events
Йохан Далин
источник
источник
Ответы:
событие popstate :
Итак, прослушивания
popstate
события и отправкиpopstate
события при использованииhistory.pushState()
должно быть достаточно, чтобы принять меры поhref
изменению:window.addEventListener('popstate', listener); const pushUrl = (href) => { history.pushState({}, '', href); window.dispatchEvent(new Event('popstate')); };
источник
pushState
Я использую этот скрипт в своем расширении "Grab Any Media" и отлично работаю ( как в случае с 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.
В любом случае использовать интервалы довольно легко, если вы не переборщите. Проверка href примерно каждые 50 мс не окажет значительного влияния на производительность, если вы беспокоитесь об этом.
источник
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; } ); } () );
источник
Вы раньше пробовали разгрузить? Это событие возникает непосредственно перед тем, как страница ответит на запрос навигации, и это должно включать изменение 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 с бегуном Karma и в Firefox вы можете захватить новый документ в готовом состоянии загрузки, если вы используете
unload + next tick
. Таким образом, вы можете добавить, например, обработчик событий загрузки или обработчик событий readystatechange или просто зарегистрировать, что браузер загружает страницу с новым URI. В Chrome с ручным тестированием (возможно, GreaseMonkey тоже) и в Opera, PhantomJS, IE10, IE11 вы не можете захватить новый документ в состоянии загрузки. В этих браузерахunload + next tick
обратный вызов вызывается на несколько сотен миллисекунд позже, чем срабатывает событие загрузки страницы. Задержка обычно составляет от 100 до 300 мс, но Opera simetime делает задержку в 750 мс для следующего тика, что пугает. Поэтому, если вы хотите получить согласованный результат во всех браузерах, вы делаете то, что хотите, после события загрузки, но нет гарантии, что местоположение не будет переопределено до этого.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
события окна соответственно. Их можно снимать, даже если вы перемещаетесь по истории назад и вперед, пока не останетесь на той же странице. Документ ими не меняется и страница не перезагружается.источник