519 Stimmen

Wie kann man warten, bis ein Element vorhanden ist?

Ich arbeite an einer Erweiterung in Chrome, und ich frage mich: Was ist der beste Weg, um herauszufinden, wann ein Element in Existenz kommt? Mit einfachen Javascript, mit einem Intervall, das überprüft, bis ein Element vorhanden ist, oder hat jQuery eine einfache Möglichkeit, dies zu tun?

7voto

Mr. Polywhirl Punkte 34960

Le observe Funktion können Sie Elemente über einen Selektor abhören.

Im folgenden Beispiel wird nach Ablauf von 2 Sekunden ein .greeting wird in die Datei .container . Da wir auf das Einfügen dieses Elements achten, können wir einen Callback haben, der beim Einfügen ausgelöst wird.

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>

6voto

Alejo JM Punkte 861

Normalerweise verwende ich dieses Snippet für Tag Manager:

<script>
(function exists() {
  if (!document.querySelector('<selector>')) {
    return setTimeout(exists);
  }
  // code when element exists
})();  
</script>

3voto

Anwar Punkte 3938

Eine Lösung, die eine Promise und die Verwendung einer Zeitüberschreitung zu ermöglichen (kompatibel mit IE 11+).

Für ein einzelnes Element (Typ Element):

"use strict";

function waitUntilElementLoaded(selector) {
    var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

    var start = performance.now();
    var now = 0;

    return new Promise(function (resolve, reject) {
        var interval = setInterval(function () {
            var element = document.querySelector(selector);

            if (element instanceof Element) {
                clearInterval(interval);

                resolve();
            }

            now = performance.now();

            if (now - start >= timeout) {
                reject("Could not find the element " + selector + " within " + timeout + " ms");
            }
        }, 100);
    });
}

Für mehrere Elemente (Typ NodeList):

"use strict";

function waitUntilElementsLoaded(selector) {
    var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

    var start = performance.now();
    var now = 0;

    return new Promise(function (resolve, reject) {
        var interval = setInterval(function () {
            var elements = document.querySelectorAll(selector);

            if (elements instanceof NodeList) {
                clearInterval(interval);

                resolve(elements);
            }

            now = performance.now();

            if (now - start >= timeout) {
                reject("Could not find elements " + selector + " within " + timeout + " ms");
            }
        }, 100);
    });
}

Beispiele:

waitUntilElementLoaded('#message', 800).then(function(element) {
    // element found and available

    element.innerHTML = '...';
}).catch(function() {
    // element not found within 800 milliseconds
});

waitUntilElementsLoaded('.message', 10000).then(function(elements) {
    for(const element of elements) {
        // ....
    }
}).catch(function(error) {
    // elements not found withing 10 seconds
});

Funktioniert sowohl für eine Liste von Elementen als auch für ein einzelnes Element.

3voto

Zaz Punkte 42583

Ein saubereres Beispiel mit MutationObserver:

new MutationObserver( mutation => {
    if (!mutation.addedNodes) return
    mutation.addedNodes.forEach( node => {
        // do stuff with node
    })
})

3voto

Diego Fortes Punkte 6850

Ich habe eine Antwort entwickelt, die von Jamie Hutber's .

Es ist ein erfolgversprechend Funktion, die Sie einstellen können:

  • maximale Anzahl von Versuchen - Standard 10 ;
  • Verzögerung in Millisekunden - Standard 100 ms .

Daher wird standardmäßig 1 Sekunde gewartet, bis das Element im DOM erscheint.

Wenn es nicht auftaucht, wird ein promise.reject con null so dass Sie den Fehler nach Ihren Wünschen behandeln können.

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

Verwendung :

async function wait(){
    try{
        const $el = await waitForElement(".llama");
        console.log($el);
    } catch(err){
        console.error("Timeout - couldn't find element.")
    }
} 

wait();

Im obigen Beispiel wird auf den Selektor gewartet .llama . Sie können eine größere Verzögerung hinzufügen und sie hier in der Konsole von StackoverFlow testen.

Fügen Sie einfach die Klasse llama zu einem beliebigen Element im DOM.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X