我正在 Chrome 中开发一个扩展程序,我想知道:找出元素何时存在的最佳方法是什么?使用普通的 javascript,间隔检查直到元素存在,或者 jQuery 是否有一些简单的方法来做到这一点?
如何等到元素存在?
IT技术
javascript
jquery
google-chrome
google-chrome-extension
2021-01-27 00:45:07
6个回答
DOMNodeInserted
由于性能问题,与其他 DOM 突变事件一起被弃用 - 推荐的方法是使用MutationObserver来观察 DOM。不过,它仅在较新的浏览器中受支持,因此您应该DOMNodeInserted
在MutationObserver
不可用时返回。
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()
我遇到了同样的问题,所以我继续为它编写了一个插件。
$(selector).waitUntilExists(function);
代码:
;(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));
这是一个核心 JavaScript 函数,用于等待元素的显示(好吧,将其插入 DOM 更准确)。
// Call the below function
waitForElementToDisplay("#div1",function(){alert("Hi");},1000,9000);
function waitForElementToDisplay(selector, callback, checkFrequencyInMs, timeoutInMs) {
var startTimeInMs = Date.now();
(function loopSearch() {
if (document.querySelector(selector) != null) {
callback();
return;
}
else {
setTimeout(function () {
if (timeoutInMs && Date.now() - startTimeInMs > timeoutInMs)
return;
loopSearch();
}, checkFrequencyInMs);
}
})();
}
此调用将查找id="div1"
每1000毫秒一次的 HTML 标记。如果找到该元素,它将显示一条警报消息Hi。如果9000毫秒后未找到元素,则此函数将停止执行。
参数:
selector
: String : 此函数查找元素 ${selector}。callback
:Function : 这是一个在找到元素时将被调用的函数。checkFrequencyInMs
: Number : 此函数每 ${checkFrequencyInMs} 毫秒检查此元素是否存在。timeoutInMs
: 数字 : 可选。此函数在 ${timeoutInMs} 毫秒后停止查找元素。
注意:选择器在https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector 中有解释
这是一个使用MutationObserver api的简单解决方案。
- 不
jQuery
- 不
Timer
- 没有第三方库
Promise
基于并与async/await
我已经在几个项目中使用过它。
function waitForElm(selector) {
return new Promise(resolve => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(mutations => {
if (document.querySelector(selector)) {
resolve(document.querySelector(selector));
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
要使用它:
waitForElm('.some-class').then((elm) => {
console.log('Element is ready');
console.log(elm.textContent);
});
或者使用异步/等待:
const elm = await waitForElm('.some-class');
我使用这种方法来等待一个元素出现,以便在那之后执行其他函数。
假设doTheRestOfTheStuff(parameters)
只有在带有 ID 的元素the_Element_ID
出现或完成加载后才应调用函数,我们可以使用,
var existCondition = setInterval(function() {
if ($('#the_Element_ID').length) {
console.log("Exists!");
clearInterval(existCondition);
doTheRestOfTheStuff(parameters);
}
}, 100); // check every 100ms