在执行代码技术之前等待页面加载的用户脚本?

IT技术 javascript jquery greasemonkey tampermonkey
2021-02-15 23:06:54

我正在编写一个 Greasemonkey 用户脚本,并希望在页面完全加载完成时执行特定代码,因为它返回了我想要显示的 div 计数。

问题是,这个特定页面有时需要一些时间才能加载所有内容。

我试过,文档$(function() { });$(window).load(function(){ });包装。然而,似乎没有一个对我有用,尽管我可能会错误地应用它们。

我能做的最好的事情就是使用一个setTimeout(function() { }, 600);有效的方法,尽管它并不总是可靠的。

在 Greasemonkey 中使用什么最好的技术来确保特定代码在页面加载完成时执行?

6个回答

Greasemonkey(通常)没有 jQuery。所以常用的方法是使用

window.addEventListener('load', function() {
    // your code here
}, false);

在您的用户脚本中

在过去的几年里我只使用过 Tampermonkey ......它的用户脚本完美地支持 document.querySelector
2021-04-19 23:06:54
添加 jQuery 就像添加@require http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js到您当前的脚本一样简单我也将它们放入模板脚本中,因为我总是使用它们。this.$ = this.jQuery = jQuery.noConflict(true);可以避免典型的冲突。
2021-04-25 23:06:54
不知道为什么人们如此渴望为所有内容添加 jquery。
2021-05-02 23:06:54
人们渴望使用 jQuery 的原因是选择器。Document.querySelector 在用户脚本中不起作用。至少就我的经验而言。
2021-05-03 23:06:54
添加对 jQuery 的依赖时
2021-05-08 23:06:54

这是一个常见问题,正如您所说,等待页面加载是不够的——因为 AJAX 可以并且确实在那之后很长时间内改变了事情。

对于这些情况,有一个标准的(ish)健壮的实用程序。waitForKeyElements()效用

像这样使用它:

// ==UserScript==
// @name     _Wait for delayed or AJAX page load
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a major design
    change introduced in GM 1.0.
    It restores the sandbox.
*/

waitForKeyElements ("YOUR_jQUERY_SELECTOR", actionFunction);

function actionFunction (jNode) {
    //-- DO WHAT YOU WANT TO THE TARGETED ELEMENTS HERE.
    jNode.css ("background", "yellow"); // example
}

提供目标页面的确切详细信息以获取更具体的示例。

@Jack,在脚本中使用 jQuery 不会将其加载到页面中,也不会在您使用@grant GM_addStyle所示内容时破坏任何内容这就是它的用途。
2021-04-23 23:06:54
如果您只希望代码运行一次,请确保将其true作为第三个参数传入waitForKeyElements
2021-04-24 23:06:54
如果目标页面上已经有 JQuery 怎么办?在页面上加载 JQuery 会破坏原始代码,但我的 GM 脚本在 JQuery 运行之前运行。我的场景的特定页面是backpack.tf,它运行JQuery 1.7.2。
2021-05-06 23:06:54

自 Greasemonkey 3.6(2015 年 11 月 20 日)起,元数据键@run-at支持新值document-idle只需将其放在 Greasemonkey 脚本的元数据块中:

// @run-at      document-idle

文档描述,如下所示:

该脚本将在页面和所有资源(图像、样式表等)加载完毕并且页面脚本运行后运行。

警告。Greasemonkey 的实现方式似乎与 Chrome/Tampermonkey 不同。因此脚本在浏览器中的工作方式可能不同。使用像waitForKeyElementsor 之类的东西仍然更健壮MutationObserver
2021-05-14 23:06:54

Brock 的回答很好,但我想为 AJAX 问题提供另一种更现代和优雅的解决方案。

由于他的脚本与大多数其他脚本一样,也使用setInterval()定期检查(300 毫秒),因此无法立即响应,并且始终存在延迟。其他解决方案使用 onload 事件,它通常会在动态页面上比您想要的更早触发。

您可以使用MutationObserver()来侦听 DOM 更改并在元素创建后立即响应它们

(new MutationObserver(check)).observe(document, {childList: true, subtree: true});

function check(changes, observer) {
    if(document.querySelector('#mySelector')) {
        observer.disconnect();
        // code
    }
}

尽管由于check()每次 DOM 更改都会触发,如果 DOM 更改非常频繁或者您的条件需要很长时间来评估,这可能会很慢,因此不要观察document而是尝试通过观察尽可能小的 DOM 子树来限制范围。

这种方法非常通用,可以应用于很多情况。要多次响应,请不要在触发时断开观察者的连接。

另一个用例是,如果您不寻找任何特定元素,而只是等待页面停止更改,则可以将其与计时器结合使用。

var observer = new MutationObserver(resetTimer);
var timer = setTimeout(action, 3000, observer); // wait for the page to stay still for 3 seconds
observer.observe(document, {childList: true, subtree: true});

// reset timer every time something changes
function resetTimer(changes, observer) {
    clearTimeout(timer);
    timer = setTimeout(action, 3000, observer);
}

function action(observer) {
    observer.disconnect();
    // code
}

这种方法非常通用,你也可以监听属性和文本的变化。只需在选项中设置attributescharacterDatatrue

observer.observe(document, {childList: true, attributes: true, characterData: true, subtree: true});

包装我的脚本$(window).load(function(){ })对我来说从来没有失败过。

也许您的页面已经完成,但仍有一些 ajax 内容正在加载。

如果是这种情况,来自Brock Adams 的这段不错的代码可以帮助您:https :
//gist.github.com/raw/2625891/waitForKeyElements.js

我通常用它来监视出现在回发中的元素

像这样使用它: waitForKeyElements("elementtowaitfor", functiontocall)