我正在Chrome中开发一个扩展,我想知道:当一个元素出现时,最好的方法是什么?使用纯javascript,间隔检查,直到一个元素存在,或jQuery有一些简单的方法来做到这一点?
当前回答
你可以这样做
$('#yourelement').ready(function() {
});
请注意,这只在从服务器请求元素时元素出现在DOM中时才有效。如果元素是通过JavaScript动态添加的,那么它将不起作用,您可能需要查看其他答案。
其他回答
这是一个纯Javascript函数,它允许你等待任何事情。设置更长的间隔,以占用更少的CPU资源。
/**
* @brief Wait for something to be ready before triggering a timeout
* @param {callback} isready Function which returns true when the thing we're waiting for has happened
* @param {callback} success Function to call when the thing is ready
* @param {callback} error Function to call if we time out before the event becomes ready
* @param {int} count Number of times to retry the timeout (default 300 or 6s)
* @param {int} interval Number of milliseconds to wait between attempts (default 20ms)
*/
function waitUntil(isready, success, error, count, interval){
if (count === undefined) {
count = 300;
}
if (interval === undefined) {
interval = 20;
}
if (isready()) {
success();
return;
}
// The call back isn't ready. We need to wait for it
setTimeout(function(){
if (!count) {
// We have run out of retries
if (error !== undefined) {
error();
}
} else {
// Try again
waitUntil(isready, success, error, count -1, interval);
}
}, interval);
}
要调用它,例如在jQuery中,使用如下代码:
waitUntil(function(){
return $('#myelement').length > 0;
}, function(){
alert("myelement now exists");
}, function(){
alert("I'm bored. I give up.");
});
受杰米·胡伯的启发,我想出了一个答案。
这是一个基于承诺的函数,你可以设置:
最大尝试次数-默认为10; 延迟(毫秒)-默认为100毫秒。
因此,默认情况下,它将等待1秒,直到元素出现在DOM上。
如果它没有出现,它将返回一个承诺。用null拒绝,这样您就可以按照您的愿望处理错误。
Code
export function _waitForElement(selector, delay = 10, tries = 100) {
const element = document.querySelector(selector);
if (!window[`__${selector}`]) {
window[`__${selector}`] = 0;
window[`__${selector}__delay`] = delay;
window[`__${selector}__tries`] = tries;
}
function _search() {
return new Promise((resolve) => {
window[`__${selector}`]++;
setTimeout(resolve, window[`__${selector}__delay`]);
});
}
if (element === null) {
if (window[`__${selector}`] >= window[`__${selector}__tries`]) {
window[`__${selector}`] = 0;
return Promise.resolve(null);
}
return _search().then(() => _waitForElement(selector));
} else {
return Promise.resolve(element);
}
}
用法:
async function wait(){
try{
const $el = await waitForElement(".llama");
console.log($el);
} catch(err){
console.error("Timeout - couldn't find element.")
}
}
wait();
在上面的例子中,它将等待选择器.llama。您可以添加更大的延迟,并在StackoverFlow的控制台上进行测试。
只需将类llama添加到DOM上的任何元素。
如果可以的话,我会尽量避开突变观察者,所以我想到了这个。它看起来类似于上面的一些其他答案。该函数将查找给定DOM调用中存在的第一个元素——className是预期的用法,但它也可以接受tagName或Id。如果您正在寻找具有给定类名或标记名的元素数量,则还可以为精确索引添加参数。
async function waitUntilElementExits(domkey,domquery,maxtime){
const delay = (ms) => new Promise(res => setTimeout(res, ms));
for(let i=0; i<maxtime; i=i+200){
await delay(200);
let elm = document[domkey](domquery);
if( (domkey == 'getElementById' && elm) || elm?.[0] ) break;
}
}
// usage
await waitUntilElementExits('getElementByClassName','some_class_name',10000)
一个返回承诺的解决方案,并允许使用超时(兼容IE 11+)。
对于单个元素(element类型):
"use strict";
function waitUntilElementLoaded(selector) {
var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var start = performance.now();
var now = 0;
return new Promise(function (resolve, reject) {
var interval = setInterval(function () {
var element = document.querySelector(selector);
if (element instanceof Element) {
clearInterval(interval);
resolve();
}
now = performance.now();
if (now - start >= timeout) {
reject("Could not find the element " + selector + " within " + timeout + " ms");
}
}, 100);
});
}
对于多个元素(类型为NodeList):
"use strict";
function waitUntilElementsLoaded(selector) {
var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var start = performance.now();
var now = 0;
return new Promise(function (resolve, reject) {
var interval = setInterval(function () {
var elements = document.querySelectorAll(selector);
if (elements instanceof NodeList) {
clearInterval(interval);
resolve(elements);
}
now = performance.now();
if (now - start >= timeout) {
reject("Could not find elements " + selector + " within " + timeout + " ms");
}
}, 100);
});
}
例子:
waitUntilElementLoaded('#message', 800).then(function(element) {
// element found and available
element.innerHTML = '...';
}).catch(function() {
// element not found within 800 milliseconds
});
waitUntilElementsLoaded('.message', 10000).then(function(elements) {
for(const element of elements) {
// ....
}
}).catch(function(error) {
// elements not found withing 10 seconds
});
既适用于元素列表,也适用于单个元素。
对于一个使用jQuery的简单方法,我发现这工作得很好:
// Wait for element to exist.
function elementLoaded(el, cb) {
if ($(el).length) {
// Element is now loaded.
cb($(el));
} else {
// Repeat every 500ms.
setTimeout(function() {
elementLoaded(el, cb)
}, 500);
}
};
elementLoaded('.element-selector', function(el) {
// Element is ready to use.
el.click(function() {
alert("You just clicked a dynamically inserted element");
});
});
在这里,我们只需每500毫秒检查一次元素是否加载,当加载成功时,我们就可以使用它。
这对于向已动态添加到文档中的元素添加单击处理程序特别有用。