JQuery обнаружение Div определенного класса был добавлен в DOM
Я использую .on()
связывать события div, которые создаются после загрузки страницы. Он отлично работает для click, mouseenter... но мне нужно знать, когда был добавлен новый div класса MyClass. Я ищу это:
$('#MyContainer').on({
wascreated: function () { DoSomething($(this)); }
}, '.MyClass');
Как мне это сделать? Мне удалось написать все приложение без плагина, и я хочу сохранить его таким.
Благодарю.
5 ответов
Спустя 3 года опыта я слушаю "элемент определенного класса, добавленный в DOM": вы просто добавляете хук в jQuery html()
функция, как это:
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 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);
Вот мой плагин, который делает именно это - jquery.initialize
Использование такое же, как вы бы использовали .each
функция, но с .initialize
функция на элементе, отличие от .each
Он также будет инициализировать элементы, добавленные в будущем, без какого-либо дополнительного кода - независимо от того, добавите ли вы его с помощью AJAX или чего-либо еще.
Инициализация имеет точно такой же синтаксис, что и с функцией.each
$(".some-element").initialize( function(){
$(this).css("color", "blue");
});
Но теперь, если новый элемент, соответствующий селектору.some-элемента, появится на странице, он будет немедленно инициализирован. Способ добавления нового элемента не важен, вам не нужно заботиться о любых обратных вызовах и т. Д.
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
Плагин основан на MutationObserver
Изучив эту и несколько других публикаций, я попытался разделить то, что мне показалось лучшим из всех, во что-то простое, что позволило мне определить, когда вставлен класс элементов, и затем воздействовать на эти элементы.
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);
});
Для меня это важно: а) целевой элемент может существовать на любой глубине внутри "добавленных узлов" и б) возможность иметь дело с элементом только при его первоначальной вставке (не нужно искать всю настройку документа или игнорировать "уже обработанный"). флаги).
Вы можете использовать мутационные события
http://www.w3.org/TR/DOM-Level-2-Events/events.html
РЕДАКТИРОВАТЬ
от 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();
Два дополнения к ответу adeneo:
(1) мы можем изменить строку
return el.classList.contains('MyClass');
Чтобы
if( el.classList ) {
return el.classList.contains('MyClass');
} else {
return false;
}
Так что мы не увидим "Uncaught TypeError: Cannot read property 'contains' of undefined"
ошибка.
(2) добавить subtree: true
в config
для рекурсивного поиска добавленных узлов во всех добавленных элементах.