Событие, когда элемент добавлен на страницу

Это ранее обсуждалось здесь: Как выполнить действие при добавлении элемента на страницу с помощью Jquery?

Респондент предложил запускать пользовательское событие всякий раз, когда на страницу добавлялся div. Однако я пишу расширение для Chrome и не имею доступа к исходному тексту страницы. Какие у меня варианты здесь? Я предполагаю, что теоретически я мог бы просто использовать setTimeout, чтобы постоянно искать наличие элемента и добавлять свое действие, если элемент там есть.

113 голосов | спросил Kevin Burke 15 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 15 Sep 2011 21:01:12 +0400 2011, 21:01:12

8 ответов


0

Поскольку события мутации DOM теперь устарели (см. примечание внизу) с последними спецификациями, и вы не можете контролировать вставленные элементы, потому что они добавляются чужим кодом, единственный вариант - постоянно проверять их.

function checkDOMChange()
{
    // check for any new element being inserted here,
    // or a particular node being modified

    // call the function again after 100 milliseconds
    setTimeout( checkDOMChange, 100 );
}

После вызова этой функции она будет запускаться каждые ххх миллисекунд. Я выбрал 100, что составляет 1/10 (одну десятую) секунды. Если вам не нужно ловить элементы в реальном времени, этого должно быть достаточно.

Edit

Как прокомментировал Бен Дэвис, спецификация DOM уровня 4 представляет Наблюдатели мутаций (также на документы Mozilla ), которые заменяют устаревшие события мутации.

ответил Jose Faeti 15 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 15 Sep 2011 21:30:08 +0400 2011, 21:30:08
0

Фактический ответ - «использовать наблюдателей мутаций» (как описано в этом вопросе: Определение, был ли элемент HTML добавлен в DOM динамически ), однако поддержка (особенно для IE) ограничена ( http://caniuse.com/mutationobserver ) .

Таким образом, фактический ответ таков: «Используйте наблюдателей за мутациями ... в конце концов. Но пока ответьте на вопрос Хосе Фаэти»:)

ответил Asfand Qazi 15 PM00000080000003631 2013, 20:33:36
0

Вы также можете использовать события CSS3 Animation, чтобы получать уведомления при добавлении определенного элемента в DOM: http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/

ответил jokeyrhyme 7 J0000006Europe/Moscow 2014, 12:11:53
0

Вы можете использовать livequery плагин для jQuery. Вы можете предоставить выражение селектора, например:

$("input[type=button].removeItemButton").livequery(function () {
    $("#statusBar").text('You may now remove items.');
});

Каждый раз, когда добавляется кнопка класса removeItemButton, в строке состояния появляется сообщение.

С точки зрения эффективности вы можете избежать этого, но в любом случае вы можете использовать плагин вместо создания собственных обработчиков событий.

Повторный ответ

Ответ выше предназначен только для обнаружения того, что элемент был добавлен в DOM через плагин.

Однако, скорее всего, подход jQuery.on() будет более подходящим, например:

$("#myParentContainer").on('click', '.removeItemButton', function(){
          alert($(this).text() + ' has been removed');
});

Если у вас есть динамическое содержимое, которое должно реагировать, например, на клики, лучше привязать события к родительскому контейнеру, используя jQuery.on.

ответил Zero Distraction 20 +04002011-10-20T08:46:57+04:00312011bEurope/MoscowThu, 20 Oct 2011 08:46:57 +0400 2011, 08:46:57
0

ETA, 24 апреля, 17 Я хотел немного упростить это с помощью async /await волшебство, так как оно делает его более лаконичным:

Использование того же самого обещанного-наблюдаемого:

const startObservable = (domNode) => {
  var targetNode = domNode;

  var observerConfig = {
    attributes: true,
    childList: true,
    characterData: true
  };

  return new Promise((resolve) => {
      var observer = new MutationObserver(function (mutations) {
         // For the sake of...observation...let's output the mutation to console to see how this all works
         mutations.forEach(function (mutation) {
             console.log(mutation.type);
         });
         resolve(mutations)
     });
     observer.observe(targetNode, observerConfig);
   })
} 

Ваша вызывающая функция может быть простой:

const waitForMutation = async () => {
    const button = document.querySelector('.some-button')
    if (button !== null) button.click()
    try {
      const results = await startObservable(someDomNode)
      return results
    } catch (err) { 
      console.error(err)
    }
}

Если вы хотите добавить тайм-аут, вы можете использовать простой шаблон Promise.race как показано здесь :

const waitForMutation = async (timeout = 5000 /*in ms*/) => {
    const button = document.querySelector('.some-button')
    if (button !== null) button.click()
    try {

      const results = await Promise.race([
          startObservable(someDomNode),
          // this will throw after the timeout, skipping 
          // the return & going to the catch block
          new Promise((resolve, reject) => setTimeout(
             reject, 
             timeout, 
             new Error('timed out waiting for mutation')
          )
       ])
      return results
    } catch (err) { 
      console.error(err)
    }
}

Оригинал

Вы можете сделать это без библиотек, но вам придется использовать некоторые вещи ES6, поэтому помните о проблемах совместимости (то есть, если ваша аудитория в основном является амишей, луддитами или, что еще хуже, пользователями IE8)

Сначала мы будем использовать API-интерфейс MutationObserver , чтобы построить объект наблюдателя. Мы завернем этот объект в обещание и resolve(), когда будет выполнен обратный вызов (h /t davidwalshblog) статья блога Дэвида Уолша о мутациях :

const startObservable = (domNode) => {
    var targetNode = domNode;

    var observerConfig = {
        attributes: true,
        childList: true,
        characterData: true
    };

    return new Promise((resolve) => {
        var observer = new MutationObserver(function (mutations) {
            // For the sake of...observation...let's output the mutation to console to see how this all works
            mutations.forEach(function (mutation) {
                console.log(mutation.type);
            });
            resolve(mutations)
        });
        observer.observe(targetNode, observerConfig);
    })
} 

Затем мы создадим generator function. Если вы еще не использовали их, то вы упускаете возможность - но краткий обзор таков: он работает как функция синхронизации, и когда он находит yield <Promise>, оно ожидает неблокирующим образом, чтобы обещание было выполнено ( Генераторы делают больше, чем это, но это то, что нам интересно здесь ).

// we'll declare our DOM node here, too
let targ = document.querySelector('#domNodeToWatch')

function* getMutation() {
    console.log("Starting")
    var mutations = yield startObservable(targ)
    console.log("done")
}

Сложность использования генераторов заключается в том, что они не «возвращаются», как обычная функция. Итак, мы будем использовать вспомогательную функцию, чтобы иметь возможность использовать генератор как обычную функцию. (опять же, h /t to dwb )

function runGenerator(g) {
    var it = g(), ret;

    // asynchronously iterate over generator
    (function iterate(val){
        ret = it.next( val );

        if (!ret.done) {
            // poor man's "is it a promise?" test
            if ("then" in ret.value) {
                // wait on the promise
                ret.value.then( iterate );
            }
            // immediate value: just send right back in
            else {
                // avoid synchronous recursion
                setTimeout( function(){
                    iterate( ret.value );
                }, 0 );
            }
        }
    })();
}

Затем в любой момент до того, как может произойти ожидаемая мутация DOM, просто запустите runGenerator(getMutation).

Теперь вы можете интегрировать мутации DOM в поток управления синхронного стиля. Как насчет этого.

ответил Brandon 19 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 19 Sep 2016 20:51:19 +0300 2016, 20:51:19
0

Существует многообещающая библиотека javascript под названием Arrive, которая выглядит как отличный способ начать пользоваться преимуществами наблюдателей мутаций, как только поддержка браузера станет обычным явлением.

https://github.com/uzairfarooq/arrive/

ответил Dave Kiss 6 AM00000020000002331 2014, 02:09:23
0

Посмотрите на этот плагин, который точно это делает - jquery.initialize

Он работает точно так же, как и каждая функция. Разница в том, что он берет выбранный вами селектор, отслеживает добавленные в будущем новые элементы, соответствующие этому селектору, и инициализирует их

Инициализация выглядит следующим образом

$(".some-element").initialize( function(){
    $(this).css("color", "blue");
});

Но теперь, если на странице появится новый соответствующий элементу селектор .some-element, он будет немедленно инициализирован.

Способ добавления нового элемента не важен, вам не нужно заботиться о каких-либо обратных вызовах и т. д.

Так что, если вы добавите новый элемент, например:

$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!

он будет мгновенно инициализирован.

Плагин основан на MutationObserver

ответил pie6k 4 FebruaryEurope/MoscowbWed, 04 Feb 2015 04:23:55 +0300000000amWed, 04 Feb 2015 04:23:55 +030015 2015, 04:23:55
0

Чистое решение JavaScript (без jQuery):

const SEARCH_DELAY = 100; // in ms

// it may run indefinitely. TODO: make it cancellable, using Promise's `reject`
function waitForElementToBeAdded(cssSelector) {
  return new Promise((resolve) => {
    const interval = setInterval(() => {
      if (element = document.querySelector(cssSelector)) {
        clearInterval(interval);
        resolve(element);
      }
    }, SEARCH_DELAY);
  });
}

console.log(await waitForElementToBeAdded('#main'));
ответил vedant 15 SatEurope/Moscow2018-12-15T12:09:25+03:00Europe/Moscow12bEurope/MoscowSat, 15 Dec 2018 12:09:25 +0300 2018, 12:09:25

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132