Самый эффективный метод обнаружения/мониторинга изменений DOM?
Мне нужен эффективный механизм для обнаружения изменений в DOM. Предпочтительно кросс-браузер, но если есть эффективные средства, которые не являются перекрестными браузерами, я могу реализовать их с помощью метода отказоустойчивого кросс-браузера.
В частности, мне нужно обнаружить изменения, которые повлияют на текст на странице, поэтому потребуются любые новые, удаленные или измененные элементы или изменения внутреннего текста (innerHTML).
У меня нет контроля над внесенными изменениями (они могут быть связаны с сторонним javascript-интерфейсом и т.д.), поэтому с этим углом нельзя подходить - мне нужно как-то "следить" за изменениями.
В настоящее время я реализовал метод "quick'n'dirty", который с интервалами проверяет body.innerHTML.length
. Разумеется, это не приведет к обнаружению изменений, которые приводят к возврату той же длины, но в этом случае "достаточно хороши" - шансы на это очень малы, и в этом проекте не удается обнаружить изменение не приведет в потерянных данных.
Проблема с body.innerHTML.length
заключается в том, что это дорого. Это может занять от 1 до 5 миллисекунд в быстром браузере, и это может сильно утомить многое - я также имею дело с большим количеством чисел iframe, и все это складывается. Я уверен, что дорогостоящее выполнение этого заключается в том, что текст innerHTML не хранится статически браузерами и должен рассчитываться из DOM каждый раз, когда он читается.
Типы ответов, которые я ищу, - это что-нибудь от "точного" (например, события) до "достаточно хорошего" - возможно, что-то вроде "quick'n'dirty" как метод innerHTML.length, но который выполняется быстрее.
EDIT:
Я должен также отметить, что, хотя было бы "хорошо" обнаружить точный элемент, который был изменен, это не является абсолютной необходимостью - только тот факт, что произошли какие-либо изменения, будет достаточно хорошим. Надеюсь, что это расширит реакцию людей. Я собираюсь исследовать Mutation Events, но мне все еще нужен резерв для поддержки IE, поэтому любые неприятные, творческие, вне квадратные идеи были бы очень желанными.
Ответы
Ответ 1
http://www.quirksmode.org/js/events/DOMtree.html
jQuery теперь поддерживает способ прикрепления событий к существующим и будущим элементам, соответствующим селектору: http://docs.jquery.com/Events/live#typefn
Еще одна интересная находка - http://james.padolsey.com/javascript/monitoring-dom-properties/
Ответ 2
Чтобы обновить эту версию, стандарт DOM4 устраняет события Mutation и заменяет их наблюдателями Mutation: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
Ответ 3
События мутации - рекомендация W3 о том, что вы ищете.
Не уверен, поддерживаются ли они все вокруг. (IE, скорее всего, не поддержит их.)
Ответ 4
Вы можете попробовать использовать события DOMNodeInserted и DOMNodeRemoved. Согласно Quirksmode, они вроде как работают в большинстве браузеров, за исключением IE...
http://www.quirksmode.org/dom/events/index.html
Ответ 5
Недавно я написал плагин, который делает именно это - jquery.initialize
Вы используете его так же, как .each
function
$(".some-element").initialize( function(){
$(this).css("color", "blue");
});
Отличие от .each
- это ваш селектор, в данном случае .some-element
и ждать новых элементов с этим селектором в будущем, если такой элемент будет добавлен, он также будет инициализирован.
В нашем случае функция инициализации просто меняет цвет элемента на синий. Поэтому, если мы добавим новый элемент (неважно, если с ajax или даже инспектором F12 или что-то еще):
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
Плагин начнет его немедленно. Также плагин гарантирует, что один элемент инициализируется только один раз. Поэтому, если вы добавите элемент, затем .deatch()
его из тела, а затем добавьте его снова, он не будет инициализирован снова.
$("<div/>").addClass('some-element').appendTo("body").detach()
.appendTo(".some-container");
//initialized only once
Плагин основан на MutationObserver
- он будет работать на IE9 и 10 с зависимостями, как описано на странице readme.
Ответ 6
jQuery Mutate делает это тоже, по умолчанию он поддерживает как height, width, scrollHeight
и т.д.... но он также может быть расширен с помощью дополнительного кода для добавления новых событий, например, если текст изменился и т.д.
http://www.jqui.net/jquery-projects/jquery-mutate-official/
Надеюсь, что это поможет