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


当前回答

更新

下面是一个更新的版本,可以使用承诺。如果达到特定的尝试次数,它也会“停止”。

function _waitForElement(selector, delay = 50, 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);
    }
  }

用法很简单,用await使用它只是确保你在一个 异步功能:

const start = (async () => {
  const $el = await _waitForElement(`.my-selector`);
  console.log($el);
})();

过时的版本

只需添加所需的选择器。一旦找到元素,就可以在回调函数中访问它。

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));

其他回答

这是写在王勇答案(最高分答案)上面的一个更好的版本。

增加的特性:您可以等待一个元素特定的时间,精确定位,以提高性能。

async function waitForElement(selector, timeout = null, location = document.body) {
    return new Promise((resolve) => {
        let element = document.querySelector(selector);
        if (element) {
            return resolve(element);
        }

        const observer = new MutationObserver(async () => {
            let element = document.querySelector(selector);
            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,
        });
    });
}

用法:

await waitForElement(".nav-alt", 500, ".main-body")

奖励:等待一个元素从DOM中消失。

async function waitForElementDeath(selector, location = document.body) {
    return new Promise((resolve) => {
        const observer = new MutationObserver(async () => {
            if (!document.querySelector(selector)) {
                resolve(true);
                observer.disconnect();
            }
        });

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

用法:

await waitForElementDeath(".Popup-div", "Popup-Container")

我认为仍然没有任何答案在这里与简单易读的工作实例。使用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文档更多 详情,如果你想了解更多信息。

更新

下面是一个更新的版本,可以使用承诺。如果达到特定的尝试次数,它也会“停止”。

function _waitForElement(selector, delay = 50, 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);
    }
  }

用法很简单,用await使用它只是确保你在一个 异步功能:

const start = (async () => {
  const $el = await _waitForElement(`.my-selector`);
  console.log($el);
})();

过时的版本

只需添加所需的选择器。一旦找到元素,就可以在回调函数中访问它。

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));

我使用这种方法等待一个元素出现,这样我就可以在那之后执行其他函数。

让我们说doTheRestOfTheStuff(参数)函数应该只在ID为the_Element_ID的元素出现或完成加载后调用,我们可以使用,

var existCondition = setInterval(function() {
 if ($('#the_Element_ID').length) {
    console.log("Exists!");
    clearInterval(existCondition);
    doTheRestOfTheStuff(parameters);
 }
}, 100); // check every 100ms

insertionQuery库呢?

insertionQuery使用CSS动画回调附加到指定的选择器,在创建元素时运行回调。此方法允许在创建元素时运行回调,而不仅仅是第一次。

从github:

用非dom事件的方式捕获节点。它使用选择器。 它不仅仅是为了更广泛的浏览器支持,在某些方面它可能比DOMMutationObserver更好。 为什么? 因为DOM事件会降低浏览器的速度,而insertionQuery不会 因为DOM Mutation Observer的浏览器支持比insertionQuery少 因为使用insertionQuery,您可以使用选择器过滤DOM更改,而没有性能开销! 广泛的支持! IE10+和其他设备(包括手机)