Альтернатива DOMNodeInserted - PullRequest
       30

Альтернатива DOMNodeInserted

29 голосов
/ 09 августа 2011

DOMNodeInserted, как известно, замедляет динамические страницы, MDN даже рекомендует не использовать его полностью, но не предоставляет никаких альтернатив.

Меня не интересует вставленный элемент, мне просто нужно знать, когда какой-либо скрипт модифицирует DOM. Есть ли лучшая альтернатива слушателям событий мутации (возможно, getElementsByTagName внутри nsiTimer)?

Ответы [ 5 ]

44 голосов
/ 27 апреля 2012

Если вы создаете веб-приложение, предназначенное для последних мобильных телефонов и новых версий браузеров (Firefox 5+, Chrome 4+, Safari 4+, iOS Safari 3+, Android 2.1+), вы можете использовать следующий код для создайте классное событие для вставки dom-узлов, и оно даже запускается на узлах, изначально являющихся частью статической разметки страницы!

Вот ссылка на полный пост с примером: http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/

Примечание по Mutation Observers: в то время как новые функции Mutation Observers в недавних браузерах отлично подходят для мониторинга простых вставок и изменений в DOM, имейте в виду, что этот метод можно использовать для гораздо большего, поскольку он позволяет Вы должны отслеживать любое совпадение с правилом CSS . Это очень мощный для многих вариантов использования, поэтому я обернул это в библиотеке здесь: https://github.com/csuwildcat/SelectorListener

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

Базовый узел вставки

CSS

@keyframes nodeInserted {  
    from {  
        outline-color: #fff; 
    }
    to {  
        outline-color: #000;
    }  
}

div.some-control {
    animation-duration: 0.01s;
    animation-name: nodeInserted;
}

JavaScript

document.addEventListener('animationstart', function(event){
    if (event.animationName == 'nodeInserted'){
        // Do something here
    }
}, true);

Прослушивание более сложных селекторных совпадений:

Это позволяет делать вещи, которые практически невозможно сделать с помощью Mutation Observers

CSS

@keyframes adjacentFocusSequence {  
    from {  
        outline-color: #fff; 
    }
    to {  
        outline-color: #000;
    }  
}

.one + .two + .three:focus {
    animation-duration: 0.01s;
    animation-name: adjacentFocusSequence;
}

JavaScript

document.addEventListener('animationstart', function(event){
    if (event.animationName == 'adjacentFocusSequence'){
        // Do something here when '.one + .two + .three' are 
        // adjacent siblings AND node '.three' is focused
    }
}, true);
11 голосов
/ 29 июня 2013

Одной новой альтернативой, кратко упомянутой @naugtur, является MutationObserver .Он предназначен для замены устаревших событий мутации, если браузер (ы), для которого вы разрабатываете, поддерживает его (например, если вы разрабатываете расширение для браузера).

0 голосов
/ 02 декабря 2014

Та же методика, что и описанная csuwldcat, была превращена в простой в использовании плагин jQuery (если это ваша вещь): https://github.com/liamdanger/jQuery.DOMNodeAppear

0 голосов
/ 15 января 2013

Это опубликовано здесь, потому что этот вопрос, где я приземлился в поисках помощи при сбое DOMNodeInserted в IE9, но, пожалуйста, обратите внимание, что это решение специально для ситуации, когда jQuery используется в контексте ASP.NET, который использует функцию End Request,Ваш пробег может варьироваться и т. Д.

В общем, мы собираемся вообще отбросить DOMNodeInserted и использовать End End для загрузки нашего обработчика событий:

OLD:

$(document).ready(function() {

$(document).bind('DOMNodeInserted', function(event){
My jQuery event handler...

 }); 
});

==========================================

NEW:

function Ajax_EndRequest {
  function2();
}

function2 (a,b){
  My jQuery event handler...
}

$(document).ready(function(){
  add_endRequest(Ajax_EndRequest); //this is what actually invokes the function upon request end.

 My jQuery event handler...//REMOVED -- don't need this now
});
0 голосов
/ 16 августа 2011

Если все, что вы хотите сделать, это вызвать событие при изменении DOM, сделайте что-то вроде этого:

var nodes=document.getElementsByTagName('*')||document.all;

function domchange(){
    alert('Hello');
}

window.setInterval(function(){
    var newnodes=document.getElementsByTagName('*')||document.all;
    if(newnodes!=nodes){
        nodes=newnodes;
        domchange();
    }
},1);
...