Событие DOM Mutation в JQuery или ванильном Javascript
Есть ли какие-либо события мутации DOM в JQuery или в ванильном Javascript, которые запускают кросс-браузер?
Чтобы уточнить, скажем, у меня на странице есть скрипт, который вставляет div в тело. У меня нет доступа к сценарию, и я не знаю, когда div был вставлен. Мне было интересно, есть ли событие мутации DOM, для которого я могу добавить слушателя, чтобы знать, когда элемент был вставлен. Я знаю, что могу использовать таймер для периодической проверки вставки, но мне не очень нравятся накладные расходы, которые это может наложить.
6 ответов
Это, конечно, хак, но почему бы не исправить патчи базовых методов DOM, используемых для вставки узлов? Есть несколько способов сделать это:
А. Вы знаете, к какому конкретному элементу будет добавлен:
var c = document.getElementById('#container');
c.__appendChild = c.appendChild;
c.appendChild = function(){
alert('new item added');
c.__appendChild.apply(c, arguments);
}
Б. Вы знаете, какой тип элемента будет добавлен:
HTMLDivElement.prototype.__appendChild = HTMLDivElement.prototype.appendChild;
HTMLDivElement.prototype.appendChild = function(){
alert('new item added');
HTMLDivElement.prototype.__appendChild(this,arguments);
}
(Обратите внимание, что решение B не поддерживается IE < 8
или любой другой браузер, который не поддерживает прототипы DOM.)
Эту же технику можно так же легко использовать для всех основных функций мутации DOM, таких как insertBefore
, replaceChild
или же removeChild
,
Это общая идея, эти демонстрации могут быть адаптированы практически для любого другого случая использования - скажем, вы хотите создать широкую сеть и поймать все дополнения независимо от типа И убедитесь, что он работает во всех браузерах, кроме IE < 8
? (см. пример С ниже)
ОБНОВИТЬ
C. Рекурсивно обходите DOM, меняйте функцию на каждом элементе, чтобы вызвать обратный вызов, а затем примените тот же патч к любому добавляемому потомку.
var DOMwatcher = function(root, callback){
var __appendChild = document.body.appendChild;
var patch = function(node){
if(typeof node.appendChild !== 'undefined' && node.nodeName !== '#text'){
node.appendChild = function(incomingNode){
callback(node, incomingNode);
patch(incomingNode);
walk(incomingNode);
__appendChild.call(node, incomingNode);
};
}
walk(node);
};
var walk = function(node){
var i = node.childNodes.length;
while(i--){
patch(node.childNodes[i]);
}
};
patch(root);
};
DOMwatcher(document.body, function(targetElement, newElement){
alert('append detected');
});
$('#container ul li').first().append('<div><p>hi</p></div>');
$('#container ul li div p').append('<a href="#foo">bar</a>');
ОБНОВЛЕНИЕ 2
Как прокомментировал Tim Down, вышеуказанное решение также не будет работать в IE < 8
так как appendChild
это не Function
и не поддерживает call
или же apply
, Я полагаю, вы всегда можете вернуться к неуклюжим, но верным setInterval
метод, если typeof document.body.appendChild !== 'function'
,
Есть некоторые устаревшие события мутации DOM, такие как DOMNodeInserted
а также DOMNodeInsertedIntoDocument
это все еще работает для меня в Chrome 14 и IE9.
Смотрите пример на http://jsfiddle.net/Kai/WTJq6/
См. Их всех в проекте W3C на http://www.w3.org/TR/DOM-Level-3-Events/
JCADE (JQuery Create и Destroy Events) сделает это. Он использует поведения для событий мутации IE и DOM для других браузеров. Он не использует события синхронизации и не переносит методы JQuery, такие как livequery.
https://github.com/snesin/jcade
$ (document).create ("a", function (event) { оповещение ( event.target); });
Думаю, не без плагина, но я не удивлюсь, если я ошибаюсь.
Мое исследование нашло несколько на выбор.
Вот один из них: http://plugins.jquery.com/project/mutation-events
Вот еще один: https://www.adaptavist.com/display/jQuery/Mutation+Events
Если вы ищете альтернативу этому методу, вот http://www.jqui.net/jquery-projects/jquery-mutate-official/ который также позволяет вам добавлять события самостоятельно и следить за практически любыми изменениями., изменение имени класса, изменение высоты, изменение ширины.