Событие DOM Mutation в JQuery или ванильном Javascript - PullRequest
24 голосов
/ 08 октября 2011

Есть ли какие-либо события мутации DOM в JQuery или в ванильном Javascript, которые запускают кросс-браузер?

Для пояснения, скажем, у меня на странице есть скрипт, который вставляет div в тело.У меня нет доступа к сценарию, и я не знаю, когда div был вставлен.Мне было интересно, есть ли событие мутации DOM, для которого я могу добавить слушателя, чтобы знать, когда элемент был вставлен.Я знаю, что могу использовать таймер для периодической проверки вставки, но мне не очень нравятся накладные расходы, которые это может наложить.

Ответы [ 6 ]

24 голосов
/ 13 октября 2011

Это, конечно, хак, но почему бы не исправить основные методы DOM, используемые для вставки узлов? Есть несколько способов сделать это:

A . Вы знаете, к какому * конкретному элементу будет добавлен:

var c = document.getElementById('#container');
c.__appendChild = c.appendChild;
c.appendChild = function(){
     alert('new item added');
     c.__appendChild.apply(c, arguments); 
}

демонстрация скрипки для A

B . Вы знаете, к какому элементу type будет добавлен:

HTMLDivElement.prototype.__appendChild = HTMLDivElement.prototype.appendChild;
HTMLDivElement.prototype.appendChild = function(){
    alert('new item added');
    HTMLDivElement.prototype.__appendChild(this,arguments); 
}

демонстрация скрипки для B

(Обратите внимание, что решение B не поддерживается IE < 8 или любым другим браузером, который не поддерживает прототипы DOM.)

Эту же технику можно так же легко использовать для всех базовых функций мутации DOM, таких как insertBefore, replaceChild или removeChild.

Это общая идея, эти демонстрации могут быть адаптированы для любого другого случая использования - скажем, вы хотите разыграть широкую сеть и поймать все дополнений независимо от типа И убедитесь, что он работает во всех всех браузерах во всех, кроме IE < 8? (см. пример C ниже)


UPDATE

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

демонстрация скрипки для C

ОБНОВЛЕНИЕ 2

Как прокомментировал Тим Даун , указанное выше решение также не будет работать в IE < 8, поскольку appendChild не является Function и не поддерживает call или apply. Я полагаю, вы всегда можете вернуться к неуклюжему, но надежному методу setInterval, если typeof document.body.appendChild !== 'function'.

8 голосов
/ 12 октября 2011

Есть некоторые устаревшие события мутации DOM, такие как DOMNodeInserted и DOMNodeInsertedIntoDocument, которые все еще работают для меня в Chrome 14 и IE9.

См. Пример на http://jsfiddle.net/Kai/WTJq6/

См. Их все на черновике W3C на http://www.w3.org/TR/DOM-Level-3-Events/

4 голосов
/ 22 февраля 2012

JCADE (JQuery Create и Destroy Events) сделает это.Он использует поведения для IE и события мутации DOM для других браузеров.Он не использует события синхронизации и не переносит методы JQuery, такие как livequery.

https://github.com/snesin/jcade


    $( document ).create( "a", function( event ) {
      alert( event.target );
    });

3 голосов
/ 08 октября 2011

Полагаю, не без плагина, но я не удивлюсь, если я ошибаюсь.

Мое исследование нашло несколько вариантов на выбор.

Вот один: http://plugins.jquery.com/project/mutation-events

Вот еще один: https://www.adaptavist.com/display/jQuery/Mutation+Events

0 голосов
/ 30 апреля 2015

Для этого можно использовать плагин livequery .В версии 1.xa таймер использовался для периодической проверки любых изменений.Тем не менее, более новая ветка версии 2.x работает без периодического таймаута (не проверено).

0 голосов
/ 20 сентября 2012

Если вы ищете альтернативу этому методу, вот http://www.jqui.net/jquery-projects/jquery-mutate-official/, который также позволяет вам добавлять события самостоятельно и следить за практически любым изменением, изменением имени класса, изменением высоты, изменением ширины.

...