Альтернатива DOMNodeInserted
Известно, что DOMNodeInserted замедляет динамические страницы, MDN даже рекомендует не использовать его вообще, но не предоставляет никаких альтернатив.
Меня не интересует вставленный элемент, мне просто нужно знать, когда какой-либо скрипт модифицирует DOM. Есть ли лучшая альтернатива слушателям событий мутации (возможно, getElementsByTagName внутри nsiTimer)?
6 ответов
Если вы создаете веб-приложение, предназначенное для последних мобильных телефонов и новых версий браузеров (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);
Прослушивание более сложных селекторных совпадений:
Это позволяет вещи, которые почти невозможно сделать с наблюдателями мутации
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);
Одна новая альтернатива, которую кратко упомянул @naugtur, - MutationObserver. Он предназначен для замены устаревших событий мутации, если браузер (ы), для которого вы разрабатываете, поддерживает его (например, если вы разрабатываете расширение для браузера).
Тот же метод, что и описанный csuwldcat, был превращен в простой в использовании плагин jQuery (если это ваша вещь): https://github.com/liamdanger/jQuery.DOMNodeAppear
попробуй использоватьcustomElements
, но не для уже созданных элементов!
customElements.define( 'insertion-triggerable', class extends HTMLElement {
connectedCallback() {
console.log( 'connected' )
}
disconnectedCallback() {
console.log( 'disconnected' )
}
adoptedCallback() {
console.log( 'adopted' )
}
} );
let element = document.createElement( 'insertion-triggerable' );
ИЛИ ЖЕ
customElements.define( 'insertion-triggerable', class extends HTMLDivElement {
// --||--
}, { extends: 'div' } );
let divElement = document.createElement( 'div', { is: 'insertion-triggerable' } );
Это опубликовано здесь, потому что этот вопрос - то, где я приземлился в поисках помощи в случае сбоя DOMNodeInserted в IE9, но, пожалуйста, обратите внимание, что это решение специально для ситуации, когда jQuery используется в контексте ASP.NET, который использует функцию End Request. Ваш пробег может варьироваться и т. Д....
По сути, мы собираемся полностью отбросить DOMNodeInserted и использовать End Request для загрузки нашего обработчика событий:
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
});
Если все, что вы хотите сделать, это вызвать событие при изменении 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);