Joh*_*lin 62 javascript dom greasemonkey dom-events
我正在为一个网站编写Greasemonkey脚本,该脚本在某些时候会修改location.href.
如何在页面上进行更改window.addEventListener时获得事件(通过或类似的东西)window.location.href?我还需要访问指向新/修改的URL的文档的DOM.
我已经看到了其他涉及超时和轮询的解决方案,但我想尽可能避免这种情况.
PHF*_*PHF 70
当活动历史记录条目更改时,将触发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'));
};
Run Code Online (Sandbox Code Playgroud)
law*_*itt 31
在支持的浏览器中,使用新的导航 API,该 API 目前正在实现作为历史记录 API 的替代品:
navigation.addEventListener('navigate', () => {
console.log('page changed');
});
Run Code Online (Sandbox Code Playgroud)
这已经在 Chromium 浏览器中运行,但截至 2024 年 1 月,Firefox 和 Safari 目前还缺少它。
它大大简化了问题,并且是专门针对单页应用程序而设计的,这是现有解决方案的主要痛点。不再有令人讨厌的昂贵MutationObserver电话!
小智 24
我在我的扩展程序"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);
};
Run Code Online (Sandbox Code Playgroud)
Tat*_*nen 23
您无法避免轮询,href更改没有任何事件.
如果你不过分,使用间隔是相当轻的.如果你担心的话,每50ms左右检查一次href对性能没有任何重大影响.
iSk*_*ore 10
onhashchange您可以使用
默认事件.
并且可以像这样使用:
function locationHashChanged( e ) {
console.log( location.hash );
console.log( e.oldURL, e.newURL );
if ( location.hash === "#pageX" ) {
pageX();
}
}
window.onhashchange = locationHashChanged;
Run Code Online (Sandbox Code Playgroud)
如果浏览器不支持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;
} );
} () );
Run Code Online (Sandbox Code Playgroud)
小智 8
通过Jquery,试试
$(window).on('beforeunload', function () {
//your code goes here on location change
});
Run Code Online (Sandbox Code Playgroud)
通过使用javascript:
window.addEventListener("beforeunload", function (event) {
//your code goes here on location change
});
Run Code Online (Sandbox Code Playgroud)
参考文档:https : //developer.mozilla.org/en-US/docs/Web/Events/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>
Run Code Online (Sandbox Code Playgroud)
但是,请注意,无论是因为脚本还是有人点击链接,您的事件都会在您离开页面时触发.您真正面临的挑战是检测事件被触发的不同原因.(如果这对你的逻辑很重要)
尝试这个脚本,它可以让您在 URL 更改时运行代码(无需页面加载,如单页面应用程序):
var previousUrl = '';
var observer = new MutationObserver(function(mutations) {
if (location.href !== previousUrl) {
previousUrl = location.href;
console.log(`URL changed to ${location.href}`);
}
});
Run Code Online (Sandbox Code Playgroud)
ReactJS 和其他 SPA应用程序使用该
history对象
可以window.history通过以下代码监听更新:
function watchHistoryEvents() {
const { pushState, replaceState } = window.history;
window.history.pushState = function (...args) {
pushState.apply(window.history, args);
window.dispatchEvent(new Event('pushState'));
};
window.history.replaceState = function (...args) {
replaceState.apply(window.history, args);
window.dispatchEvent(new Event('replaceState'));
};
window.addEventListener('popstate', () => console.log('popstate event'));
window.addEventListener('replaceState', () => console.log('replaceState event'));
window.addEventListener('pushState', () => console.log('pushState event'));
}
watchHistoryEvents();
Run Code Online (Sandbox Code Playgroud)
根据“Leonardo Ciaccio”的答案,修改后的代码在这里:即删除 for 循环并重新分配 Body 元素(如果删除)
window.addEventListener("load", function () {
let oldHref = document.location.href,
bodyDOM = document.querySelector("body");
function checkModifiedBody() {
let tmp = document.querySelector("body");
if (tmp != bodyDOM) {
bodyDOM = tmp;
observer.observe(bodyDOM, config);
}
}
const observer = new MutationObserver(function (mutations) {
if (oldHref != document.location.href) {
oldHref = document.location.href;
console.log("the location href is changed!");
window.requestAnimationFrame(checkModifiedBody)
}
});
const config = {
childList: true,
subtree: true
};
observer.observe(bodyDOM, config);
}, false);
Run Code Online (Sandbox Code Playgroud)