我正在Chrome中开发一个扩展,我想知道:当一个元素出现时,最好的方法是什么?使用纯javascript,间隔检查,直到一个元素存在,或jQuery有一些简单的方法来做到这一点?


当前回答

受杰米·胡伯的启发,我想出了一个答案。

这是一个基于承诺的函数,你可以设置:

最大尝试次数-默认为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上的任何元素。

其他回答

您可以监听DOMNodeInserted或DOMSubtreeModified事件,每当有新元素添加到DOM时,这些事件就会触发。

还有一个LiveQuery jQuery插件,它可以检测创建的新元素:

$("#future_element").livequery(function(){
    //element created
});

你可以这样做

$('#yourelement').ready(function() {

});

请注意,这只在从服务器请求元素时元素出现在DOM中时才有效。如果元素是通过JavaScript动态添加的,那么它将不起作用,您可能需要查看其他答案。

我认为仍然没有任何答案在这里与简单易读的工作实例。使用MutationObserver接口来检测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); }); }); <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <button>New content</button> <div id="newContent"></div>

注意:关于MutationObserver的西班牙语Mozilla文档更多 详情,如果你想了解更多信息。

你也可以使用getElementById代替querySelector

这个函数和 https://stackoverflow.com/a/61511955/10798137

  async function waitForElementById(id, timeout = null, location = document.body) {
    return new Promise((resolve) => {
        let element = document.getElementById(id);
        if (element) {
            return resolve(element);
        }

        const observer = new MutationObserver(async () => {
            let element = document.getElementById(id);
            if (element) {
                resolve(element);
                observer.disconnect();
            } else {
                if (timeout) {
                    async function timeOver() {
                        return new Promise((resolve) => {
                            setTimeout(() => {
                                observer.disconnect();
                                resolve(false);
                            }, timeout);
                        });
                    }
                    resolve(await timeOver());
                }
            }
        });

        observer.observe(location, {
            childList: true,
            subtree: true,
        });
    });

使用它


    waitForElement("tag_id", 500).then((elm) => {
      console.log(elm)
    })

Or


    var elm = async waitForElement("tag_id", 500)

下面是一个使用MutationObserver api的简单解决方案。

没有jQuery 没有计时器 没有第三方库 基于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);
});

或者使用async/await:

const elm = await waitForElm('.some-class');