it-swarm.com.ru

Есть слушатель изменения DOM JavaScript / jQuery?

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

365
Fletcher Moore

Несколько лет спустя, теперь официально существует лучшее решение. Наблюдатели мутации 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 года; вы можете проверить спецификации на наличие изменений.)

441
apsillers

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

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

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

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

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

203
Anurag

Многие сайты используют 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();
        }
    });
    
40
wOxxOm

Другой подход в зависимости от того, как вы меняете 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.

27
Zac Imboden

В дополнение к "необработанным" инструментам, предоставляемым 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);
}
6
Xan