我正在Chrome中开发一个扩展,我想知道:当一个元素出现时,最好的方法是什么?使用纯javascript,间隔检查,直到一个元素存在,或jQuery有一些简单的方法来做到这一点?
当前回答
一个使用MutationObserver的更清晰的例子:
new MutationObserver( mutation => {
if (!mutation.addedNodes) return
mutation.addedNodes.forEach( node => {
// do stuff with node
})
})
其他回答
你可以这样做
$('#yourelement').ready(function() {
});
请注意,这只在从服务器请求元素时元素出现在DOM中时才有效。如果元素是通过JavaScript动态添加的,那么它将不起作用,您可能需要查看其他答案。
由于性能问题,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()
我也有同样的问题,所以我继续写了一个插件。
$(选择).waitUntilExists(函数);
代码:
;(function ($, window) {
var intervals = {};
var removeListener = function(selector) {
if (intervals[selector]) {
window.clearInterval(intervals[selector]);
intervals[selector] = null;
}
};
var found = 'waitUntilExists.found';
/**
* @function
* @property {object} jQuery plugin which runs handler function once specified
* element is inserted into the DOM
* @param {function|string} handler
* A function to execute at the time when the element is inserted or
* string "remove" to remove the listener from the given selector
* @param {bool} shouldRunHandlerOnce
* Optional: if true, handler is unbound after its first invocation
* @example jQuery(selector).waitUntilExists(function);
*/
$.fn.waitUntilExists = function(handler, shouldRunHandlerOnce, isChild) {
var selector = this.selector;
var $this = $(selector);
var $elements = $this.not(function() { return $(this).data(found); });
if (handler === 'remove') {
// Hijack and remove interval immediately if the code requests
removeListener(selector);
}
else {
// Run the handler on all found elements and mark as found
$elements.each(handler).data(found, true);
if (shouldRunHandlerOnce && $this.length) {
// Element was found, implying the handler already ran for all
// matched elements
removeListener(selector);
}
else if (!isChild) {
// If this is a recurring search or if the target has not yet been
// found, create an interval to continue searching for the target
intervals[selector] = window.setInterval(function () {
$this.waitUntilExists(handler, shouldRunHandlerOnce, true);
}, 500);
}
}
return $this;
};
}(jQuery, window));
受杰米·胡伯的启发,我想出了一个答案。
这是一个基于承诺的函数,你可以设置:
最大尝试次数-默认为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上的任何元素。
我使用这种方法等待一个元素出现,这样我就可以在那之后执行其他函数。
让我们说doTheRestOfTheStuff(参数)函数应该只在ID为the_Element_ID的元素出现或完成加载后调用,我们可以使用,
var existCondition = setInterval(function() {
if ($('#the_Element_ID').length) {
console.log("Exists!");
clearInterval(existCondition);
doTheRestOfTheStuff(parameters);
}
}, 100); // check every 100ms