window.location.href 更改时的事件

IT技术 javascript dom greasemonkey dom-events
2021-01-14 00:22:24

我正在为一个站点编写 Greasemonkey 脚本,该脚本在某些时候会修改location.href.

window.addEventListenerwindow.location.href页面发生变化时,如何获得事件(通过或类似的方式)我还需要访问指向新/修改过的 url 的文档的 DOM。

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

6个回答

我在我的扩展程序“Grab Any Media”中使用了这个脚本并且工作正常(比如youtube案例

var oldHref = document.location.href;

window.onload = function() {
    var bodyList = document.querySelector("body")

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

可能适用于 youtube 的唯一解决方案:[仅报告] 拒绝从 ' youtube.com/sw.js '创建工作人员,因为它违反了以下内容安全策略指令:“worker-src 'none'”。
2021-03-21 00:22:24
不知何故,我喜欢这种方法......感觉有点 RxJs-ish :)
2021-03-26 00:22:24
开箱即用,我的用例没有问题,上帝保佑!令人讨厌的是,目前还没有本地事件(popstate 对我不起作用)但是有一天!我会使用window.addEventListener("load", () => {})而不是 window.onload :)
2021-03-27 00:22:24
突变观察者
2021-03-28 00:22:24
伙计,这太棒了。迄今为止我见过的最聪明的解决方案
2021-03-28 00:22:24

弹出状态事件

当活动历史记录条目更改时,会触发 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
2021-03-28 00:22:24
这假设你有可见性或知道 pushState 是否被调用......它不会在任何地方工作,就像上面状态的评论一样
2021-04-02 00:22:24
这并不总是有效,它依赖于要触发的 popstate 事件。例如在 youtube 中导航它不会触发,只有当您在历史记录中按后退或前进
2021-04-07 00:22:24
但是在加载内容之前 popstate 会触发吗?
2021-04-11 00:22:24

您无法避免轮询,没有任何用于 href 更改的事件。

无论如何,如果你不过度使用间隔是很轻的。如果您担心,每 50 毫秒左右检查一次 href 不会对性能产生任何显着影响。

这不是真的。
2021-03-25 00:22:24
@AlexanderMills:幸好有这些新的解决方案popstatehashchange
2021-03-28 00:22:24
不幸的是,这个答案在 2020 年仍然是正确的。popstate 仅在用户使用前进/后退按钮时触发,而 hashchange 仅在哈希更改时触发。除非你能控制导致位置改变的代码,否则你必须轮询🤷‍♀️
2021-03-29 00:22:24
@MartinZvarík 即使在 2010 年,也可以使用卸载事件加上微任务或宏任务来加载新文档。
2021-04-05 00:22:24

onhashchange您可以使用 一个默认事件。

记录在这里

并且可以这样使用:

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;
    } );
} () );
window.addEventListener("hashchange", funcRef, false);
2021-03-12 00:22:24
Hashchange 事件仅在您的 URL 包含以“#”符号开头的部分时才会发送,通常用于锚链接。否则不会火。
2021-03-16 00:22:24

通过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