Вопрос по jquery – JQuery обнаружения Div определенного класса был добавлен в DOM

70

Я использую.on() связывать события div, которые создаются после загрузки страницы. Он отлично работает для click, mouseenter ... но мне нужно знать, когда был добавлен новый div класса MyClass. Я ищу это:

<code>$('#MyContainer').on({

  wascreated: function () { DoSomething($(this)); }

}, '.MyClass');
</code>

Как мне это сделать? Мне удалось написать все приложение без плагина, и я хочу сохранить его таким.

Благодарю.

ДубликатEvent when element added to page Dan Dascalescu
Это ваш собственный код, который генерирует элементы? Если это так, вы можете проверить в момент создания и действовать соответствующим образом. Surreal Dreams
вы можете использовать $ (& quot; div / your-selector & quot;). hasClass (& quot; MyClass & quot;); проверить, есть ли у div определенный класс или нет. Я думаю, вы могли бы использовать этот API-интерфейс для вашего использования. KBN
Да, это правда, но с помощью .on () я могу связывать события в document.ready, и тогда мне не нужно беспокоиться о связывании, когда я генерирую HTML. Я ищу то же поведение с DoSomething. frenchie
.on () только для событий. Вы можете настроить пользовательское событие, но вам все равно придется инициировать это событие при создании новых элементов. Surreal Dreams

Ваш Ответ

5   ответов
12

3 года опыта спустя, вот как я слушаю"element of a certain class added to the DOM": вы просто добавляете хук в jQueryhtml() функция, как это:

function Start() {

   var OldHtml = window.jQuery.fn.html;

   window.jQuery.fn.html = function () {

     var EnhancedHtml = OldHtml.apply(this, arguments);

     if (arguments.length && EnhancedHtml.find('.MyClass').length) {

         var TheElementAdded = EnhancedHtml.find('.MyClass'); //there it is
     }

     return EnhancedHtml;
   }
}

$(Start);

Это работает, если вы используете jQuery, что я и делаю. И это не зависит от конкретного события браузераDOMNodeInserted, который не является кросс-браузерным. Я также добавил ту же реализацию для.prepend()

В целом, это работает как очарование для меня, и, надеюсь, для вас тоже.

Хм. Я бы пояснил, что это работает, если вы используете исключительно jQuery.html помощник для изменения DOM, а не просто "используя jQuery" в общем. Элементы добавлены с помощью, скажем,jQuery.append не вызовет это событие.
Почему понизить? Это на самом деле работает: нет плагина и нет хакерской функции setTimeout. frenchie
Отклонено - это действительный вариант - почему в мире (!!!) это было понижено ?????? Дэн, CSS3 анимации не XBC:caniuse.com/#search=keyframes; davidwalsh.name/detect-node-insertion.
Да, и именно поэтому я пояснил, что я добавил ту же реализацию с .preprend (), и если вы используете .append (), то сделайте то же самое с .append () frenchie
Есть гораздо более быстрый подход, использующийCSS3 animations, Библиотека с открытым исходным кодом также предоставляет гораздо более простой код:insertionQ('#intercom-container').every(function(/element){ element.style.display = 'none'; });
5

Вы можете использовать мутационные события

http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mutationevents

РЕДАКТИРОВАТЬ

из MDN:https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events

Устаревшие Эта функция была удалена из Интернета. Хотя некоторые браузеры все еще могут поддерживать его, он находится в процессе удаления. Не используйте его в старых или новых проектах. Страницы или веб-приложения, использующие его, могут сломаться в любое время.

Наблюдатели мутаций - это предлагаемая замена мутационных событий в DOM4. Они должны быть включены в Firefox 14 и Chrome 18.

https://developer.mozilla.org/en/docs/Web/API/MutationObserver

MutationObserver предоставляет разработчикам способ реагировать на изменения в DOM. Он предназначен для замены событий мутации, определенных в спецификации событий DOM3.

Пример использования

Следующий пример был взят изhttp://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/.

// select the target node
var target = document.querySelector('#some-id');

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });    
});

// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };

// pass in the target node, as well as the observer options
observer.observe(target, config);

// later, you can stop observing
observer.disconnect();
Теперь, когда IE10 - EOL, можно с уверенностью сказать,MutationObserver широко поддерживается.
События мутации в значительной степени устарели в соответствии сmdnв пользу MutationObservers
79

domManip метод, чтобы перехватить все манипуляции с jQuery dom и посмотреть, какие элементы были вставлены и т. д., но команда jQuery закрыла это в jQuery 3.0+, поскольку это, как правило, не очень хорошее решение для подключения к таким методам jQuery, и они сделали это так внутреннийdomManip метод больше не доступен за пределами основного кода jQuery.

События мутации также устарели, так как раньше можно было сделать что-то вроде

$(document).on('DOMNodeInserted', function(e) {
    if ( $(e.target).hasClass('MyClass') ) {
       //element with .MyClass was inserted.
    }
});

этого следует избегать, и сегодня вместо него следует использовать Mutation Observers, который будет работать следующим образом

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log(mutation)
        if (mutation.addedNodes && mutation.addedNodes.length > 0) {
            // element added to DOM
            var hasClass = [].some.call(mutation.addedNodes, function(el) {
                return el.classList.contains('MyClass')
            });
            if (hasClass) {
                // element has class `MyClass`
                console.log('element ".MyClass" added');
            }
        }
    });
});

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

observer.observe(document.body, config);
хорошо спасибо; похоже, он работает, но не на IE8. frenchie
Сначала я использовал ваш ответ, но проблема в том, что он не работал в кросс-браузерном режиме, была проблемой. Затем я быстро нашел обходной путь, чтобы избежать этой проблемы. И затем, несколько недель назад, эта проблема обнаружения вставки узлов снова появилась в моем коде. На этот раз код, который я разместил в своем ответе, работает ТОЧНО, как и должно быть, кросс-браузер и ничего не глючит. Вот почему я переместил свой ответ как принятый; Вот как работает SO, OP решает, какой ответ он принимает, и толпа голосует за ответы. Со временем люди будут голосовать и решать, какой ответ им больше подходит. frenchie
А также я хотел сказать, что вы несколько раз помогали мне с качественными ответами, которые спасли мой день. Изменение принятого ответа на мой зависит исключительно от кода и от того, насколько он соответствует проблеме, которую мне пришлось решить. frenchie
Firefox и webkit в значительной степени должны быть в порядке, но поддержка этого довольно слабая в IE. Это должно работать в IE9, но, вероятно, не так много в IE8. Я знаю, что видел обходные пути, и я действительно не проверял это в IE, поэтому сначала проверьте его, если он не работает, затем посмотрите, есть ли обходной путь. Есть плагин, который выглядит так, как будто он добавляет поддержку IEhere, но не попробовали, просто нашли его в поиске Google.
43

jquery.initialize

Использование такое же, как и вы.each функция, но с.initialize функция на элементе, отличие от.each Он также будет инициализировать элементы, добавленные в будущем, без какого-либо дополнительного кода - независимо от того, добавите ли вы его с помощью AJAX или чего-либо еще.

Initialize have exacly the same syntax as with .each function

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

But now if new element matching .some-element selector will appear on page, it will be instanty initialized. The way new item is added is not important, you dont need to care about any callbacks etc.

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

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

хорошая работа, очень полезный плагин! :)
аааа это именно то что мне нужно, спасибо!
Да, действительно очень крутой плагин. Хорошая работа! frenchie
Это работает исключительно хорошо!
Огромное спасибо.
13

я попытался перевести то, что мне показалось лучшим из всех, во что-то простое, что позволило мне определить, когда вставлен класс элементов, а затемact on those elements.

function onElementInserted(containerSelector, elementSelector, callback) {

    var onMutationsObserved = function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length) {
                var elements = $(mutation.addedNodes).find(elementSelector);
                for (var i = 0, len = elements.length; i < len; i++) {
                    callback(elements[i]);
                }
            }
        });
    };

    var target = $(containerSelector)[0];
    var config = { childList: true, subtree: true };
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    var observer = new MutationObserver(onMutationsObserved);    
    observer.observe(target, config);

}

onElementInserted('body', '.myTargetElement', function(element) {
    console.log(element);
});

Для меня важно, что это позволяет a) целевому элементу существовать на любой глубине в пределах "добавленных узлов". и b) способность иметь дело с элементом только при его первоначальной вставке (нет необходимости выполнять поиск по всему параметру документа или игнорировать «уже обработанные» флаги).

Ваше состояние должно бытьif(mutation.addedNodes.length) так какaddedNodes а такжеremovedNodes массивы всегда есть вmutation типаchildList (проверено в IE11, Chrome53, FF49). Еще +1, потому что твой единственный ответ, гдеaddedNodes Считается (callback вызывается только при добавлении узла); не только в этой теме, но и во многих других. Все остальные просто вызываютcallback для всех мутаций, даже если узел удаляется.
Спасибо, Вивек. Код был обновлен.

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