Есть ли прослушиватель изменений JavaScript / jQuery DOM?



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

678   5  

5 ответов:

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

Edit

этот ответ теперь устарел. Смотрите ответ от apsillers.

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

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

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

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


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


Extensions-specific: обнаружение изменений URL в фон/страница событие.

есть расширенный API для работы с оборудованием: webNavigation,webRequest, но мы будем использовать простой хром.вешалки.onUpdated прослушиватель событий, который отправляет скрипт содержанием:

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

  • фон.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');
        }
    });
    
  • содержание.js

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        if (msg === 'url-update') {
            doSomething();
        }
    });
    

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

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

Comments

    Ничего не найдено.