我正在Chrome中开发一个扩展,我想知道:当一个元素出现时,最好的方法是什么?使用纯javascript,间隔检查,直到一个元素存在,或jQuery有一些简单的方法来做到这一点?
当前回答
下面的observe函数将允许您通过选择器监听元素。
在下面的例子中,2秒过后,.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)); 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; } <div class="container"></div>
更新
下面是一个实验性的async/await示例。
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()); })(); 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; } <div class="container"></div>
其他回答
insertionQuery库呢?
insertionQuery使用CSS动画回调附加到指定的选择器,在创建元素时运行回调。此方法允许在创建元素时运行回调,而不仅仅是第一次。
从github:
用非dom事件的方式捕获节点。它使用选择器。 它不仅仅是为了更广泛的浏览器支持,在某些方面它可能比DOMMutationObserver更好。 为什么? 因为DOM事件会降低浏览器的速度,而insertionQuery不会 因为DOM Mutation Observer的浏览器支持比insertionQuery少 因为使用insertionQuery,您可以使用选择器过滤DOM更改,而没有性能开销! 广泛的支持! IE10+和其他设备(包括手机)
由于性能问题,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()
下面是一个函数,充当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>
如果可以的话,我会尽量避开突变观察者,所以我想到了这个。它看起来类似于上面的一些其他答案。该函数将查找给定DOM调用中存在的第一个元素——className是预期的用法,但它也可以接受tagName或Id。如果您正在寻找具有给定类名或标记名的元素数量,则还可以为精确索引添加参数。
async function waitUntilElementExits(domkey,domquery,maxtime){
const delay = (ms) => new Promise(res => setTimeout(res, ms));
for(let i=0; i<maxtime; i=i+200){
await delay(200);
let elm = document[domkey](domquery);
if( (domkey == 'getElementById' && elm) || elm?.[0] ) break;
}
}
// usage
await waitUntilElementExits('getElementByClassName','some_class_name',10000)
简单的Javascript。
cont elementExist = setInterval(() => {
var elm = document.getElementById("elementId")
if (elm!=null)
// call your function here to do something
clearInterval(elementExist);
}
}, 100);
注意:这将阻塞其他执行
推荐文章
- 如何为Firebase构建云函数,以便从多个文件部署多个函数?
- 如何发送推送通知到web浏览器?
- AngularJS:工厂和服务?
- js:将一个组件包装成另一个组件
- 父ng-repeat从子ng-repeat的访问索引
- JSHint和jQuery: '$'没有定义
- 模仿JavaScript中的集合?
- 用JavaScript验证电话号码
- 如何在HTML5中改变视频的播放速度?
- 谷歌地图API v3:我可以setZoom后fitBounds?
- 用jQuery检查Internet连接是否存在?
- 如何使用滑动(或显示)函数在一个表行?
- ES6/2015中的null安全属性访问(和条件赋值)
- 与push()相反;
- JS字符串“+”vs concat方法