Есть слушатель изменения DOM JavaScript / jQuery? - PullRequest
365 голосов
/ 16 мая 2010

По сути, я хочу, чтобы скрипт выполнялся при изменении содержимого DIV. Поскольку сценарии являются отдельными (контентный скрипт в расширении Chrome и скрипте веб-страницы), мне нужен способ просто наблюдать изменения в состоянии DOM. Я мог бы настроить опрос, но это кажется небрежным.

Ответы [ 5 ]

441 голосов
/ 18 июля 2012

Несколько лет спустя, теперь официально существует лучшее решение. Наблюдатели мутации DOM4 являются заменой устаревших событий мутации DOM3. Они в настоящее время реализованы в современных браузерах как MutationObserver (или как префикс WebKitMutationObserver в старых версиях Chrome):

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations, observer) {
    // fired when a mutation occurs
    console.log(mutations, observer);
    // ...
});

// define what element should be observed by the observer
// and what types of mutations trigger the callback
observer.observe(document, {
  subtree: true,
  attributes: true
  //...
});

В этом примере прослушиваются изменения DOM document и всего его поддерева, и он запускает изменения атрибутов элемента, а также структурные изменения. Черновик спецификации имеет полный список действительных свойств прослушивателя мутаций :

childList

  • Установите на true, если нужно наблюдать мутации у детей-мишеней.

атрибуты

  • Установить на true, если должны наблюдаться мутации в атрибутах цели.

CharacterData

  • Установите на true, если должны наблюдаться мутации в данных цели.

поддерево

  • Установите на true, если нужно наблюдать мутации не только цели, но и потомков цели.

attributeOldValue

  • Устанавливается на true, если attributes имеет значение true и значение атрибута цели перед записью мутации.

characterDataOldValue

  • Установите на true, если characterData установлено в true и данные цели перед записью мутации.

attributeFilter

  • Установить список локальных имен атрибутов (без пространства имен), если необходимо соблюдать не все мутации атрибутов.

(Этот список действителен по состоянию на апрель 2014 года; вы можете проверить спецификации на наличие изменений.)

203 голосов
/ 16 мая 2010

Редактировать

Этот ответ устарел. Смотрите ответ по апсиллерам .

Поскольку это расширение Chrome, вы можете также использовать стандартное событие DOM - DOMSubtreeModified. Смотрите поддержку этого события во всех браузерах. Поддерживается в Chrome с 1.0.

$("#someDiv").bind("DOMSubtreeModified", function() {
    alert("tree changed");
});

См. Рабочий пример здесь .

40 голосов
/ 15 сентября 2016

Многие сайты используют AJAX для динамического добавления / показа / изменения контента. Иногда он используется вместо навигации внутри сайта, поэтому текущий URL-адрес изменяется программно, и в этом случае браузер не выполняет автоматически скрипты содержимого, поскольку страница не извлекается полностью с удаленного сервера.


Обычные JS-методы обнаружения изменений страницы, доступные в скрипте содержимого .


Специфично для расширений: обнаружение изменений URL на фоне / странице событий .

Существует расширенный API для работы с навигацией: webNavigation , webRequest , но мы будем использовать простой chrome.tabs.onUpdated обработчик событий, который отправляет сообщение скрипту содержимого:

  • manifest.json:
    объявить фон / страница события
    объявить скрипт содержания
    добавить "tabs" разрешение .

  • background.js

    var rxLookfor = /^https?:\/\/(www\.)?google\.(com|\w\w(\.\w\w)?)\/.*?[?#&]q=/;
    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
        if (rxLookfor.test(changeInfo.url)) {
            chrome.tabs.sendMessage(tabId, 'url-update');
        }
    });
    
  • content.js

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        if (msg === 'url-update') {
            doSomething();
        }
    });
    
27 голосов
/ 24 мая 2012

Другой подход в зависимости от того, как вы меняете div.Если вы используете JQuery для изменения содержимого div с помощью его метода html (), вы можете расширять этот метод и вызывать функцию регистрации каждый раз, когда помещаете html в div.

(function( $, oldHtmlMethod ){
    // Override the core html method in the jQuery object.
    $.fn.html = function(){
        // Execute the original HTML method using the
        // augmented arguments collection.

        var results = oldHtmlMethod.apply( this, arguments );
        com.invisibility.elements.findAndRegisterElements(this);
        return results;

    };
})( jQuery, jQuery.fn.html );

Мы просто перехватываем вызовыдля html () вызовите функцию регистрации с этим, которая в контексте относится к целевому элементу, получающему новое содержимое, затем мы передаем вызов исходной функции jquery.html ().Не забудьте вернуть результаты исходного метода html (), потому что JQuery ожидает его для цепочки методов.

Для получения дополнительной информации о переопределении и расширении метода, посмотрите http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htm,, где я и написалфункция закрытия.Также ознакомьтесь с руководством по плагинам на сайте JQuery.

6 голосов
/ 10 мая 2016

В дополнение к «необработанным» инструментам, предоставляемым MutationObserver API , существуют «удобные» библиотеки для работы с мутациями DOM.

Учтите: MutationObserver представляет каждое изменение DOM вусловия поддеревьев.Так что, если вы, например, ожидаете вставки определенного элемента, он может быть глубоко внутри дочерних элементов mutations.mutation[i].addedNodes[j].

Другая проблема - когда ваш собственный код, в ответ на мутации, изменяетсяDOM - вам часто хочется его отфильтровать.

Хорошая удобная библиотека, которая решает такие проблемы: mutation-summary (отказ от ответственности: я не автор, просто довольный пользователь),который позволяет вам задавать запросы того, что вас интересует, и получать именно это.

Пример базового использования из документов:

var observer = new MutationSummary({
  callback: updateWidgets,
  queries: [{
    element: '[data-widget]'
  }]
});

function updateWidgets(summaries) {
  var widgetSummary = summaries[0];
  widgetSummary.added.forEach(buildNewWidget);
  widgetSummary.removed.forEach(cleanupExistingWidget);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...