我正在Chrome中开发一个扩展,我想知道:当一个元素出现时,最好的方法是什么?使用纯javascript,间隔检查,直到一个元素存在,或jQuery有一些简单的方法来做到这一点?
当前回答
我采取@Yong Wong的解决方案,但它有一个可选的超时,你可以指定根节点从哪里你想等待元素。
完整的异步/等待。
const $ = (selector, opts) => {
let timeout = undefined;
let root = undefined;
if (opts) {
({ root, timeout } = opts);
}
if (root === undefined) root = document.body;
const nodeFound = root.querySelector(selector);
if (nodeFound) return new Promise(resolve => resolve(nodeFound));
return new Promise((resolve, reject) => {
let callback = () => {
observer.disconnect();
};
const _resolve = (node) => {
callback();
resolve(node);
};
const _reject = (err) => {
callback();
reject(err);
};
if (timeout && timeout > 0) {
const handle = setTimeout(() => {
_reject(new Error("Element not found: timeout exceeded."));
}, timeout);
callback = () => {
observer.disconnect();
clearTimeout(handle);
};
}
const observer = new MutationObserver(mutations => {
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
if (addedNode.matches(selector)) {
_resolve(addedNode);
return;
}
}
}
});
observer.observe(root, {
childList: true,
subtree: true,
});
});
}
示例调用:
// wait for 10 seconds for 'div.bla-bla-bla' to appear as a child of 'div.some-container'
await $("div.bla-bla-bla", {
timeout: 10000,
root: document.querySelector("div.some-container")
});
其他回答
由于性能问题,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()
你可以这样做
$('#yourelement').ready(function() {
});
请注意,这只在从服务器请求元素时元素出现在DOM中时才有效。如果元素是通过JavaScript动态添加的,那么它将不起作用,您可能需要查看其他答案。
如果你想让它在一段时间后停止查看(超时),那么下面的jQuery可以工作。10秒后会暂停。我需要使用这段代码而不是纯JS,因为我需要通过名称选择输入,并且在实现其他一些解决方案时遇到了麻烦。
// Wait for element to exist.
function imageLoaded(el, cb,time) {
if ($(el).length) {
// Element is now loaded.
cb($(el));
var imageInput = $('input[name=product\\[image_location\\]]');
console.log(imageInput);
} else if(time < 10000) {
// Repeat every 500ms.
setTimeout(function() {
time = time+500;
imageLoaded(el, cb, time)
}, 500);
}
};
var time = 500;
imageLoaded('input[name=product\\[image_location\\]]', function(el) {
//do stuff here
},time);
下面是一个函数,充当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); }); .content { padding: 1em; border: solid 1px black; overflow-y: auto; } #innerContent { height: 100px; } #outerContent { height: 200px; } #log { font-family: Courier; font-size: 10pt; } <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>
您可以监听DOMNodeInserted或DOMSubtreeModified事件,每当有新元素添加到DOM时,这些事件就会触发。
还有一个LiveQuery jQuery插件,它可以检测创建的新元素:
$("#future_element").livequery(function(){
//element created
});
推荐文章
- 在React Native中使用Fetch授权头
- 为什么我的球(物体)没有缩小/消失?
- 如何使用jQuery检测页面的滚动位置
- if(key in object)或者if(object. hasownproperty (key)
- 一元加/数字(x)和parseFloat(x)之间的区别是什么?
- angularjs中的compile函数和link函数有什么区别
- 删除绑定中添加的事件监听器
- 如何在JSON中使用杰克逊更改字段名
- 很好的初学者教程socket.io?
- HtmlSpecialChars在JavaScript中等价于什么?
- React: 'Redirect'没有从' React -router-dom'中导出
- 如何在React中使用钩子强制组件重新渲染?
- 我如何使用Jest模拟JavaScript的“窗口”对象?
- 我如何等待一个承诺完成之前返回一个函数的变量?
- 在JavaScript中根据键值查找和删除数组中的对象