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


当前回答

你也可以使用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)

其他回答

这里有一个核心JavaScript函数,用于等待元素的显示(好吧,将其插入到DOM中更准确)。

// Call the below function
waitForElementToDisplay("#div1",function(){alert("Hi");},1000,9000);

function waitForElementToDisplay(selector, callback, checkFrequencyInMs, timeoutInMs) {
  var startTimeInMs = Date.now();
  (function loopSearch() {
    if (document.querySelector(selector) != null) {
      callback();
      return;
    }
    else {
      setTimeout(function () {
        if (timeoutInMs && Date.now() - startTimeInMs > timeoutInMs)
          return;
        loopSearch();
      }, checkFrequencyInMs);
    }
  })();
}

这个调用将每1000毫秒查找id="div1"的HTML标记。如果找到元素,它将显示一条警报消息Hi。如果在9000毫秒后没有找到任何元素,该函数将停止执行。

参数:

String:该函数查找元素${selector}。 callback: Function:这是一个函数,如果找到元素将被调用。 checkFrequencyInMs: Number:该函数每${checkFrequencyInMs}毫秒检查该元素是否存在。 timeoutInMs: Number:可选。该函数在${timeoutInMs}毫秒后停止查找元素。

注意:选择器的解释在https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

我采取@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") 
});

你可以这样做

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

});

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

这是一个纯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);
}

要调用它,例如在jQuery中,使用如下代码:

waitUntil(function(){
    return $('#myelement').length > 0;
}, function(){
    alert("myelement now exists");
}, function(){
    alert("I'm bored. I give up.");
});

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

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

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