Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用户脚本在执行代码技术之前等待页面加载?_Javascript_Jquery_Greasemonkey_Tampermonkey - Fatal编程技术网

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

Javascript 用户脚本在执行代码技术之前等待页面加载?,javascript,jquery,greasemonkey,tampermonkey,Javascript,Jquery,Greasemonkey,Tampermonkey,我正在编写一个Greasemonkey用户脚本,希望在页面完全完成加载时执行特定的代码,因为它返回我想要显示的div计数 问题是,在加载所有内容之前,此特定页面有时需要花费一些时间 我已经试过了,document$(function(){})和$(窗口).load(函数(){})包装器。然而,它们似乎都不适合我,尽管我可能用错了 我能做的最好的事情就是使用setTimeout(function(){},600)虽然并不总是可靠,但仍然有效 在Greasemonkey中使用什么最佳技术来确保在页面

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

问题是,在加载所有内容之前,此特定页面有时需要花费一些时间

我已经试过了,document
$(function(){})
$(窗口).load(函数(){})包装器。然而,它们似乎都不适合我,尽管我可能用错了

我能做的最好的事情就是使用
setTimeout(function(){},600)虽然并不总是可靠,但仍然有效

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

Greasemonkey(通常)没有jQuery。因此,常用的方法是使用

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

在您的用户脚本中

将我的脚本包装在
$(窗口)中。加载(函数(){})
对我来说从未失败过

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

如果是这样的话,来自的这段代码可以帮助您:

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


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

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

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

像这样使用它:

/==UserScript==
//@name\u等待延迟或AJAX页面加载
//@包括http://YOUR_SERVER.COM/YOUR_PATH/*
//@需要http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
//@需要https://gist.github.com/raw/2625891/waitForKeyElements.js
//@grant GM_addStyle
//==/UserScript==
/*-需要@grant指令来处理主要设计
GM 1.0中引入的更改。
它会恢复沙箱。
*/
WaitForkElements(“您的查询选择器”,actionFunction);
函数actionFunction(jNode){
//--在此处对目标元素执行所需操作。
jNode.css(“背景”、“黄色”);//示例
}

请提供目标页面的详细信息,以获得更具体的示例。

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

/@在文档空闲时运行
报告对其进行了如下描述:

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

很好,但我想为AJAX问题提供另一种更现代、更优雅的解决方案。由于他的脚本还使用
setInterval()
定期检查(300ms),因此无法立即响应

如果需要立即响应,可以使用
MutationObserver()
侦听DOM更改,并在创建元素后立即响应

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

function check(changes, observer) {
    if(document.querySelector('#mySelector')) {
        observer.disconnect();
        // code
    }
}
虽然由于每次DOM更改都会触发
check()
,但如果DOM经常更改,或者您的条件需要很长时间才能评估,则这可能会很慢

另一个用例是,如果您不寻找任何特定元素,而只是等待页面停止更改。您也可以将其与
setTimeout()
结合起来等待

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

function resetTimer(changes, observer) {
    clearTimeout(timer);
    timer = setTimeout(action, 3000, observer);
}

function action(o) {
    o.disconnect();
    // code
}
此方法用途广泛,您还可以侦听属性和文本更改。只需在选项中将
attributes
characterData
设置为
true

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

若要操作节点(如获取节点值或更改样式),可以使用此函数等待这些节点

const waitFor=(…选择器)=>新承诺(解析=>{
常数延迟=500
常数f=()=>{
常量元素=选择器.map(选择器=>document.querySelector(选择器))
if(elements.every(element=>element!=null)){
解析(元素)
}否则{
设置超时(f,延迟)
}
}
f()
})
然后使用
promise。然后使用

// scripts don't manipulate nodes
waitFor('video', 'div.sbg', 'div.bbg').then(([video, loading, videoPanel])=>{
    console.log(video, loading, videoPanel)
    // scripts may manipulate these nodes
})
或者使用
async&wait

//this semicolon is needed if none at end of previous line
;(async () => {
    // scripts don't manipulate nodes
    const [video, loading, videoPanel] = await waitFor('video','div.sbg','div.bbg')
    console.log(video, loading, video)
    // scripts may manipulate these nodes
})()

下面是一个示例

,用于检测XHR是否在网页中完成加载,然后触发某些函数。 我从你那里得到的,它真的有用

    //This overwrites every XHR object's open method with a new function that adds load and error listeners to the XHR request. When the request completes or errors out, the functions have access to the method and url variables that were used with the open method.
    //You can do something more useful with method and url than simply passing them into console.log if you wish.
    //https://stackoverflow.com/questions/43282885/how-do-i-use-javascript-to-store-xhr-finished-loading-messages-in-the-console
    (function() {
        var origOpen = XMLHttpRequest.prototype.open;
        XMLHttpRequest.prototype.open = function(method, url) {
            this.addEventListener('load', function() {
                console.log('XHR finished loading', method, url);
                display();
            });

            this.addEventListener('error', function() {
                console.log('XHR errored out', method, url);
            });
            origOpen.apply(this, arguments);
        };
    })();
    function display(){
        //codes to do something;
    }
但是如果页面中有许多XHR,我不知道如何过滤确定的XHR

另一个方法是waitforkeylements(),这很好。
有供Greasemonkey使用的样品。

您可以使用
(函数init(){var counter=document.getElementById('id-of-element');if(counter){/*对计数器元素*/}执行某些操作{setTimeout(init,0);}}()
以持续轮询元素是否存在。这是最通用的解决方案。Greasemonkey的兄弟Tampermonkey和Scriptish支持更多的值,包括
文档空闲
上下文菜单
,它们可能有用。Greasemonkey似乎也适用于
文档空闲
,尽管到目前为止还没有文档记录。@RobW这对我有用,谢谢。如果目标页面上已经有JQuery怎么办?在页面上加载JQuery会破坏原始代码,但我的GM脚本会在JQuery运行之前运行。我的场景的特定页面是backpack.tf,它正在运行JQuery 1.7.2。@Jack,在脚本中使用JQuery不会将其加载到页面中,当您使用
@grant GM_addStyle
时,它也不会破坏任何内容,如图所示。这就是它的目的。如果您只想让代码运行一次,请确保将
true
作为第三个参数传递给
waitforkyelments
,jQuery就像add
@所要求的那样简单http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
添加到当前脚本。我也将它们放入了模板脚本中,因为我总是使用它们。同时放入
this.$=this.jQue