2010-08-19 172 views
27

我正在为某个站点写一个Greasemonkey脚本,它在某些时候修改了location.hrefwindow.location.href更改时的事件

window.location.href在页面上发生变化时,如何获得事件(通过window.addEventListener或类似的东西)?我也需要访问指向新的/修改后的url的文档的DOM。

我见过涉及超时和轮询的其他解决方案,但如果可能的话,我想避免这种情况。

回答

31

popstate event

的popstate事件被触发主动历史条目更改时。 [...]的popstate事件仅做一个浏览器动作,如后退按钮点击(或在JavaScript调用history.back())触发

所以,听popstate事件和发送使用history.pushState()popstate事件应该足以承担href变化采取行动:

window.addEventListener('popstate', listener); 

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

但内容加载之前Popstate会启动吗? – user2782001 2017-03-23 21:29:31

14

你不能避免轮询,没有任何href更改的事件。

反过来说,使用间隔时间很轻松。如果你担心这个问题,每50ms检查一次href就不会对性能产生任何显着影响。

+10

亚克西说不好 – 2017-01-19 06:29:41

+1

@AlexanderMills:幸运的是有'popstate'和'hashchange'这些新的解决方案。 – 2017-04-24 20:07:11

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 2010-08-19 13:32:30

+0

我也需要访问新的DOM,我更新了这个问题以澄清这一点。 – 2010-08-19 13:33:14

+0

行 - 没有考虑到'哈希'情况 - 会考虑那个。 至于能够访问新的DOM,那么你就不幸运了(就从事件处理程序中访问这个事件而言),因为事件将在新DOM加载之前触发。您可能可以将逻辑合并到新页面的onload事件中,但是您可能在识别是否需要执行该页面每次加载的逻辑时遇到同样的问题。 你能否提供一些关于你想要实现的更多细节,包括页面流? – belugabob 2010-08-19 13:38:41

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; 

如果浏览器不支持oldURLnewURL可以绑定像这样:

//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案例

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

};