mat*_*ven 213 javascript jquery google-chrome google-chrome-extension
我正在研究Chrome中的扩展程序,我想知道:什么是找出元素何时出现的最佳方法?使用普通的javascript,检查直到元素存在的间隔,或jQuery有一些简单的方法来做到这一点?
hug*_*hsk 137
DOMNodeInserted
因性能问题而被弃用以及其他DOM突变事件 - 推荐的方法是使用MutationObserver来监视DOM.它仅在较新的浏览器中受支持,因此您应该DOMNodeInserted
在MutationObserver
不可用时再次使用.
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (!mutation.addedNodes) return
for (var i = 0; i < mutation.addedNodes.length; i++) {
// do things to your newly added nodes here
var node = mutation.addedNodes[i]
}
})
})
observer.observe(document.body, {
childList: true
, subtree: true
, attributes: false
, characterData: false
})
// stop watching using:
observer.disconnect()
Run Code Online (Sandbox Code Playgroud)
Rya*_*ter 112
我遇到了同样的问题,所以我继续为它写了一个插件.
$(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));
Run Code Online (Sandbox Code Playgroud)
Eti*_*ier 65
这是一个等待元素显示的核心JavaScript函数.
参数:
selector
:此函数查找元素$ {selector}time
:此函数检查此元素是否每隔$ {time}毫秒存在.
function waitForElementToDisplay(selector, time) {
if(document.querySelector(selector)!=null) {
alert("The element is displayed, you can put your code instead of this alert.")
return;
}
else {
setTimeout(function() {
waitForElementToDisplay(selector, time);
}, time);
}
}
Run Code Online (Sandbox Code Playgroud)作为一个例子,设置selector="#div1"
并time=5000
会寻找HTML标签,其id="div1"
每5000毫秒.
Yon*_*ang 36
对于那些习惯于承诺并且不想使用任何第三方库或计时器的人来说,这是一个简单的解决方案。
我已经在我的项目中使用它一段时间了
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
});
});
}
Run Code Online (Sandbox Code Playgroud)
要使用它:
waitForElm('.some-class').then(elm => console.log(elm.textContent));
Run Code Online (Sandbox Code Playgroud)
或使用异步/等待
const elm = await waitForElm('.some-classs')
Run Code Online (Sandbox Code Playgroud)
ser*_*erg 24
每当将新元素添加到DOM时,您都可以监听DOMNodeInserted
或DOMSubtreeModified
触发事件.
还有LiveQuery jQuery插件可以检测何时创建新元素:
$("#future_element").livequery(function(){
//element created
});
Run Code Online (Sandbox Code Playgroud)
Sil*_*fer 23
我认为这里仍然没有任何简单易读的工作示例的答案。使用MutationObserver interface
检测 DOM 更改,如下所示:
var observer = new MutationObserver(function(mutations) {
if ($("p").length) {
console.log("Exist, lets do something");
observer.disconnect();
//We can disconnect observer once the element exist if we dont want observe more changes in the DOM
}
});
// Start observing
observer.observe(document.body, { //document.body is node target to observe
childList: true, //This is a must have for the observer with subtree
subtree: true //Set to true if changes must also be observed in descendants.
});
$(document).ready(function() {
$("button").on("click", function() {
$("p").remove();
setTimeout(function() {
$("#newContent").append("<p>New element</p>");
}, 2000);
});
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>New content</button>
<div id="newContent"></div>
Run Code Online (Sandbox Code Playgroud)
注意: 如果您想了解更多信息,西班牙语 Mozilla文档
MutationObserver
会更详细。
Spl*_*ynx 22
你可以做
$('#yourelement').ready(function() {
});
Run Code Online (Sandbox Code Playgroud)
请注意,这仅在从服务器请求时元素存在于DOM中时才有效.如果通过JavaScript动态添加元素,它将无法工作,您可能需要查看其他答案.
pri*_*ime 17
我用这种方法等待一个元素出现,所以我可以在那之后执行其他函数.
假设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
Run Code Online (Sandbox Code Playgroud)
Hed*_*ith 11
对于使用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");
});
});
Run Code Online (Sandbox Code Playgroud)
在这里,我们只需检查每500ms以查看元素是否已加载,何时加载,我们可以使用它.
这对于将单击处理程序添加到已动态添加到文档的元素特别有用.
怎么样insertionQuery库?
insertionQuery使用附加到指定的选择器的CSS动画回调来在创建元素时运行回调.此方法允许在创建元素时运行回调,而不仅仅是第一次.
来自github:
捕获节点的非dom-event方式.它使用选择器.
它不仅仅适用于更广泛的浏览器支持,对于某些事情来说,它可能比DOMMutationObserver更好.
为什么?
- 因为DOM事件会降低浏览器的速度,而insertQuery则不会
- 因为DOM Mutation Observer比insertQuery具有更少的浏览器支持
- 因为使用insertQuery,您可以使用选择器过滤DOM更改,而不会产生性能开销!
广泛的支持!
IE10 +以及其他任何东西(包括手机)
小智 8
你可以试试这个:
const wait_until_element_appear = setInterval(() => {
if ($(element).length !== 0) {
// some code
clearInterval(wait_until_element_appear);
}
}, 0);
Run Code Online (Sandbox Code Playgroud)
这个解决方案对我来说非常有用
只需添加所需的选择器。一旦找到该元素,您就可以在回调函数中进行访问。
const waitUntilElementExists = (selector, callback) => {
const el = document.querySelector(selector);
if (el){
return callback(el);
}
setTimeout(() => waitUntilElementExists(selector, callback), 500);
}
waitUntilElementExists('.wait-for-me', (el) => console.log(el));
Run Code Online (Sandbox Code Playgroud)
下面的函数observe
将允许您通过选择器监听元素。
在下面的示例中,2 秒过去后,a.greeting
将被插入到.container
. 由于我们正在侦听此元素的插入,因此我们可以有一个在插入时触发的回调。
const observe = (selector, callback, targetNode = document.body) =>
new MutationObserver(mutations => [...mutations]
.flatMap((mutation) => [...mutation.addedNodes])
.filter((node) => node.matches && node.matches(selector))
.forEach(callback))
.observe(targetNode, { childList: true, subtree: true });
const createGreeting = () => {
const el = document.createElement('DIV');
el.textContent = 'Hello World';
el.classList.add('greeting');
return el;
};
const container = document.querySelector('.container');
observe('.greeting', el => console.log('I have arrived!', el), container);
new Promise(res => setTimeout(() => res(createGreeting()), 2000))
.then(el => container.appendChild(el));
Run Code Online (Sandbox Code Playgroud)
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
body { display: flex; }
.container { display: flex; flex: 1; align-items: center; justify-content: center; }
.greeting { font-weight: bold; font-size: 2em; }
Run Code Online (Sandbox Code Playgroud)
<div class="container"></div>
Run Code Online (Sandbox Code Playgroud)
这是一个实验性的异步/等待示例。
const sleep = (ms) => new Promise((res) => setTimeout(res, ms));
const observe = (selector, targetNode = document.body) =>
new Promise(res => {
new MutationObserver(mutations =>
res([...mutations]
.flatMap((mutation) => [...mutation.addedNodes])
.find((node) => node.matches && node.matches(selector))))
.observe(targetNode, { childList: true, subtree: true });
});
const createGreeting = () => {
const el = document.createElement('DIV');
el.textContent = 'Hello World';
el.classList.add('greeting');
return el;
};
const container = document.querySelector('.container');
observe('.greeting', container)
.then(el => console.log('I have arrived!', el));
(async () => {
await sleep(2000);
container.appendChild(createGreeting());
})();
Run Code Online (Sandbox Code Playgroud)
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
body { display: flex; }
.container { display: flex; flex: 1; align-items: center; justify-content: center; }
.greeting { font-weight: bold; font-size: 2em; }
Run Code Online (Sandbox Code Playgroud)
<div class="container"></div>
Run Code Online (Sandbox Code Playgroud)
这是一个函数,它充当MutationObserver的瘦包装器.唯一的要求是浏览器支持MutationObserver; 没有依赖于JQuery.运行下面的代码段以查看一个有效的示例.
function waitForMutation(parentNode, isMatchFunc, handlerFunc, observeSubtree, disconnectAfterMatch) {
var defaultIfUndefined = function(val, defaultVal) {
return (typeof val === "undefined") ? defaultVal : val;
};
observeSubtree = defaultIfUndefined(observeSubtree, false);
disconnectAfterMatch = defaultIfUndefined(disconnectAfterMatch, false);
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes) {
for (var i = 0; i < mutation.addedNodes.length; i++) {
var node = mutation.addedNodes[i];
if (isMatchFunc(node)) {
handlerFunc(node);
if (disconnectAfterMatch) observer.disconnect();
};
}
}
});
});
observer.observe(parentNode, {
childList: true,
attributes: false,
characterData: false,
subtree: observeSubtree
});
}
// Example
waitForMutation(
// parentNode: Root node to observe. If the mutation you're looking for
// might not occur directly below parentNode, pass 'true' to the
// observeSubtree parameter.
document.getElementById("outerContent"),
// isMatchFunc: Function to identify a match. If it returns true,
// handlerFunc will run.
// MutationObserver only fires once per mutation, not once for every node
// inside the mutation. If the element we're looking for is a child of
// the newly-added element, we need to use something like
// node.querySelector() to find it.
function(node) {
return node.querySelector(".foo") !== null;
},
// handlerFunc: Handler.
function(node) {
var elem = document.createElement("div");
elem.appendChild(document.createTextNode("Added node (" + node.innerText + ")"));
document.getElementById("log").appendChild(elem);
},
// observeSubtree
true,
// disconnectAfterMatch: If this is true the hanlerFunc will only run on
// the first time that isMatchFunc returns true. If it's false, the handler
// will continue to fire on matches.
false);
// Set up UI. Using JQuery here for convenience.
$outerContent = $("#outerContent");
$innerContent = $("#innerContent");
$("#addOuter").on("click", function() {
var newNode = $("<div><span class='foo'>Outer</span></div>");
$outerContent.append(newNode);
});
$("#addInner").on("click", function() {
var newNode = $("<div><span class='foo'>Inner</span></div>");
$innerContent.append(newNode);
});
Run Code Online (Sandbox Code Playgroud)
.content {
padding: 1em;
border: solid 1px black;
overflow-y: auto;
}
#innerContent {
height: 100px;
}
#outerContent {
height: 200px;
}
#log {
font-family: Courier;
font-size: 10pt;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Create some mutations</h2>
<div id="main">
<button id="addOuter">Add outer node</button>
<button id="addInner">Add inner node</button>
<div class="content" id="outerContent">
<div class="content" id="innerContent"></div>
</div>
</div>
<h2>Log</h2>
<div id="log"></div>
Run Code Online (Sandbox Code Playgroud)
这是一个纯 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);
}
Run Code Online (Sandbox Code Playgroud)
要调用它,例如在 jQuery 中,请使用以下内容:
waitUntil(function(){
return $('#myelement').length > 0;
}, function(){
alert("myelement now exists");
}, function(){
alert("I'm bored. I give up.");
});
Run Code Online (Sandbox Code Playgroud)
这是使用原始Javascript的Promise返回解决方案(没有混乱的回调)。默认情况下,它每200毫秒检查一次。
function waitFor(selector) {
return new Promise(function (res, rej) {
waitForElementToDisplay(selector, 200);
function waitForElementToDisplay(selector, time) {
if (document.querySelector(selector) != null) {
res(document.querySelector(selector));
}
else {
setTimeout(function () {
waitForElementToDisplay(selector, time);
}, time);
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我通常将这段代码用于跟踪代码管理器:
<script>
(function exists() {
if (!document.querySelector('<selector>')) {
return setTimeout(exists);
}
// code when element exists
})();
</script>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
219097 次 |
最近记录: |