Самый эффективный метод обнаружения / мониторинга изменений DOM? - PullRequest
44 голосов
/ 16 марта 2010

Мне нужен эффективный механизм для обнаружения изменений в DOM. Предпочтительно кросс-браузер, но если есть какие-либо эффективные средства, которые , а не кросс-браузер, я могу реализовать их с помощью отказоустойчивого метода кросс-браузер.

В частности, мне нужно обнаружить изменения, которые повлияют на текст на странице, поэтому потребуются любые новые, удаленные или измененные элементы или изменения внутреннего текста (innerHTML).

Я не контролирую внесенные изменения (они могут быть связаны с включением стороннего javascript и т. Д.), Поэтому к нему нельзя подходить с этой точки зрения - мне нужно как-то «отслеживать» изменения.

В настоящее время я реализовал метод "quick'n'dirty", который проверяет body.innerHTML.length с интервалами. Это, конечно, не обнаружит изменений, которые приведут к возвращению одинаковой длины, но в этом случае «достаточно хороши» - шансы на это чрезвычайно малы, и в этом проекте не обнаружение изменений не приведет к в потерянных данных.

Проблема с body.innerHTML.length в том, что это дорого. Это может занять от 1 до 5 миллисекунд в быстром браузере, и это может сильно затормозить - я также имею дело с большим количеством iframes, и все это складывается. Я почти уверен, что дороговизна этого процесса заключается в том, что текст innerHTML не хранится статически браузерами и должен вычисляться из DOM каждый раз, когда его читают.

Типы ответов, которые я ищу, - что угодно, от «точного» (например, события) до «достаточно хорошего» - возможно, такого же «быстрого и ненадежного», как метод innerHTML.length, но выполняемого быстрее.

EDIT: Я также должен отметить, что хотя было бы «хорошо» обнаружить точный элемент, который был изменен, это не является абсолютной необходимостью - просто факт того, что было любое изменение, будет достаточно хорошим. Надеюсь, это расширяет ответы людей. Я собираюсь исследовать Mutation Events, но мне все еще нужен запасной вариант для поддержки IE, так что любые дурацкие, креативные, нестандартные идеи будут приветствоваться.

Ответы [ 6 ]

31 голосов
/ 07 марта 2014

Чтобы обновить это, стандарт DOM4 покончил с Mutation Events и заменил их на Mutation Observers: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

10 голосов
/ 16 марта 2010

http://www.quirksmode.org/js/events/DOMtree.html

jQuery теперь поддерживает способ прикрепления событий к существующим и будущим элементам, соответствующим селектору: http://docs.jquery.com/Events/live#typefn

Еще одна интересная находка - http://james.padolsey.com/javascript/monitoring-dom-properties/

8 голосов
/ 16 марта 2010

События мутации - это рекомендации W3 того, что вы ищете ..

Не уверен, что они поддерживаются повсюду .. (IE, скорее всего, не будет поддерживать их ..)

1 голос
/ 06 февраля 2015

Я недавно написал плагин, который делает именно это - jquery.initialize

Вы используете его так же, как .each функция

$(".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 с зависимостями, как описано на странице чтения .

1 голос
/ 16 марта 2010

Вы можете попробовать использовать события DOMNodeInserted и DOMNodeRemoved. Согласно Quirksmode, они работают в большинстве браузеров, за исключением IE ...

http://www.quirksmode.org/dom/events/index.html

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

jQuery Mutate делает это тоже, по умолчанию поддерживает как height, width, scrollHeight и т. Д., Но также может быть расширен небольшим дополнительным кодом для добавления новых событий как посмотреть, изменился ли текст и т.д ...

http://www.jqui.net/jquery-projects/jquery-mutate-official/

Надеюсь, это поможет

...