我正在Chrome中开发一个扩展,我想知道:当一个元素出现时,最好的方法是什么?使用纯javascript,间隔检查,直到一个元素存在,或jQuery有一些简单的方法来做到这一点?
当前回答
由于性能问题,DOMNodeInserted和其他DOM突变事件已被弃用——推荐的方法是使用MutationObserver监视DOM。不过,它只在较新的浏览器中受支持,所以当MutationObserver不可用时,您应该回到DOMNodeInserted上。
let observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (!mutation.addedNodes) return
for (let i = 0; i < mutation.addedNodes.length; i++) {
// do things to your newly added nodes here
let node = mutation.addedNodes[i]
}
})
})
observer.observe(document.body, {
childList: true
, subtree: true
, attributes: false
, characterData: false
})
// stop watching using:
observer.disconnect()
其他回答
我通常使用标签管理器的这个片段:
<script>
(function exists() {
if (!document.querySelector('<selector>')) {
return setTimeout(exists);
}
// code when element exists
})();
</script>
你可以这样做
$('#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.");
});
这是写在王勇答案(最高分答案)上面的一个更好的版本。
增加的特性:您可以等待一个元素特定的时间,精确定位,以提高性能。
async function waitForElement(selector, timeout = null, location = document.body) {
return new Promise((resolve) => {
let element = document.querySelector(selector);
if (element) {
return resolve(element);
}
const observer = new MutationObserver(async () => {
let element = document.querySelector(selector);
if (element) {
resolve(element);
observer.disconnect();
} else {
if (timeout) {
async function timeOver() {
return new Promise((resolve) => {
setTimeout(() => {
observer.disconnect();
resolve(false);
}, timeout);
});
}
resolve(await timeOver());
}
}
});
observer.observe(location, {
childList: true,
subtree: true,
});
});
}
用法:
await waitForElement(".nav-alt", 500, ".main-body")
奖励:等待一个元素从DOM中消失。
async function waitForElementDeath(selector, location = document.body) {
return new Promise((resolve) => {
const observer = new MutationObserver(async () => {
if (!document.querySelector(selector)) {
resolve(true);
observer.disconnect();
}
});
observer.observe(location, {
childList: true,
subtree: true,
});
});
}
用法:
await waitForElementDeath(".Popup-div", "Popup-Container")
对于一个使用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毫秒检查一次元素是否加载,当加载成功时,我们就可以使用它。
这对于向已动态添加到文档中的元素添加单击处理程序特别有用。