【发布时间】:2013-09-24 18:32:21
【问题描述】:
我有一个正在尝试为其创建 Greasemonkey 脚本的应用程序。它利用大量的 jQuery 和 AJAX 来动态加载内容。
我注意到,每次加载新项目时,URL确实会发生变化,即使页面没有刷新。
是否可以在页面上放置一个侦听器以在每次 URL 更改时重新启动脚本?
【问题讨论】:
标签: javascript ajax greasemonkey
我有一个正在尝试为其创建 Greasemonkey 脚本的应用程序。它利用大量的 jQuery 和 AJAX 来动态加载内容。
我注意到,每次加载新项目时,URL确实会发生变化,即使页面没有刷新。
是否可以在页面上放置一个侦听器以在每次 URL 更改时重新启动脚本?
【问题讨论】:
标签: javascript ajax greasemonkey
您如何执行此操作取决于站点/应用程序以及您尝试执行的操作。 以下是您的选择,首先是最简单且最强大的:
不要试图捕捉 URL 更改。 Use calls to waitForKeyElements() to act on the parts of the various pages that you wanted to manipulate in the first place. 这巧妙地处理了所有其他方法固有的一系列时序问题。
另请参阅:"Choosing and activating the right controls on an AJAX-driven site"。
Just poll for URL changes.它很简单,在实践中效果很好,除了技术#1之外,时间问题比其他所有方法都少。
如果站点使用 AJAX 来更改 片段(也称为“哈希”),fire on the hashchange event。唉,越来越少的 AJAX 网站这样做了。
使用 Mutation Observers 来监控 <title> 标签的变化。 大多数 AJAX 页面也足以更改标题。不过,这可能会在您的目标内容加载之前触发。
Hack into the history.pushState function. 这可以更快地通知页面更改,但在 95% 的情况下,它会在目标元素加载之前触发。您通常仍需要一个计时器。另外,它在用户脚本环境中带来了跨范围问题。
作为参考,这是一个投票示例。它仍然是最好的、准系统、跨浏览器、包罗万象的方法:
/*--- Note, gmMain () will fire under all these conditions:
1) The page initially loads or does an HTML reload (F5, etc.).
2) The scheme, host, or port change. These all cause the browser to
load a fresh page.
3) AJAX changes the URL (even if it does not trigger a new HTML load).
*/
var fireOnHashChangesToo = true;
var pageURLCheckTimer = setInterval (
function () {
if ( this.lastPathStr !== location.pathname
|| this.lastQueryStr !== location.search
|| (fireOnHashChangesToo && this.lastHashStr !== location.hash)
) {
this.lastPathStr = location.pathname;
this.lastQueryStr = location.search;
this.lastHashStr = location.hash;
gmMain ();
}
}
, 111
);
function gmMain () {
console.log ('A "New" page has loaded.');
// DO WHATEVER YOU WANT HERE.
}
【讨论】:
gmMain() 中所做的任何事情放在 setTimeout() 中(我使用 500 毫秒),除此之外,当您导航回来时,再次调用该函数,您可以找到 AJAX 内容的容器,并在第一个元素中添加一个类,如果该类存在,则不执行任何操作。
“我注意到 URL 每次都会改变”与很多 AJAX 会导致我认为他们正在使用 History API。如果是这种情况,请查看window.onpopstate。这应该会在使用 History API 的每个 URL 更改时触发。
【讨论】:
unsafeWindow 和/或使用addEventListener?