2010-08-19 3 views
27

Я пишу сценарий Greasemonkey для сайта, который в какой-то момент изменяет location.href.Событие при изменении window.location.href

Как я могу получить событие (через window.addEventListener или что-то подобное), когда window.location.href меняется на странице? Мне также нужен доступ к DOM документа, указывающий на новый/измененный URL.

Я видел другие решения, которые включают тайм-ауты и опросы, но я хотел бы избежать этого, если это возможно.

ответ

31

popstate event:

popstate событие вызывается, когда активные изменения входа в историю. [...] Это событие popstate срабатывает только выполнив действие браузера, такие как щелчок на кнопке Back (или вызова history.back() в JavaScript)

Так, слушая popstate события и посылая popstate события при использовании history.pushState() должно быть достаточно, чтобы принять меры по href изменениям:

window.addEventListener('popstate', listener); 

const pushUrl = (href) => { 
    history.pushState({}, '', href); 
    window.dispatchEvent(new Event('popstate')); 
}; 
+0

Но будет ли всплывающий огонь перед загрузкой содержимого? – user2782001

14

Вы не можете избежать опроса, нет никаких событий для изменения href.

Использование интервалов довольно легко в любом случае, если вы не заходите за борт. Проверка href каждые 50 мс или около того не окажет существенного влияния на производительность, если вы беспокоитесь об этом.

+10

Хлоп, что не является хорошим –

+1

@AlexanderMills: к счастью, есть новые решения 'popstate' и' hashchange'. –

6

Вы пробовали 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> 

Остерегайтесь, однако, что ваше мероприятие будет срабатывать когда вы уйдете со страницы, является ли это из-за сценария, или кто-то нажав на ссылку. Ваша настоящая проблема - это выявление различных причин увольнения. (Если это важно для вашей логике)

+0

Я не уверен, что это сработает, потому что часто изменения хэша не связаны с перезагрузкой страницы. – samandmoore

+0

Мне также нужен доступ к новому DOM, я обновил вопрос, чтобы уточнить это. –

+0

ОК - не считал ситуацию «хэш» - подумает об этом. Что касается возможности доступа к новой DOM, то вам не повезло (насколько это доступно для обработчика события), поскольку событие будет срабатывать до того, как будет загружена новая DOM. Возможно, вы сможете включить логику в событие onload на новой странице, но у вас могут быть те же проблемы в отношении определения необходимости выполнения логики для каждой загрузки этой страницы. Можете ли вы предоставить более подробную информацию о том, чего вы пытаетесь достичь, включая поток страниц? – belugabob

2

Существует onhashchange события по умолчанию, которые вы можете использовать.

Documented HERE

И может быть использован, как это:

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; 
    }); 
}()); 
1

Я использую это сценарий в моем расширении «Захватить любые медиа» и работать нормально (как youtube case)

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); 

}; 
Смежные вопросы