Есть ли прослушиватель изменений JavaScript / jQuery DOM?
по существу, я хочу, чтобы скрипт выполнялся при изменении содержимого DIV. Поскольку сценарии являются отдельными (сценарий содержимого в chrome extension & webpage script), мне нужен способ просто наблюдать за изменениями в состоянии DOM. Я мог бы настроить опрос, но это кажется небрежным.
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 обнаружения изменений страницы доступны в скрипт контент.
MutationObserver ( docs) чтобы буквально обнаружить изменения DOM:
прослушивателя событий для сайтов, которые сигнализируют об изменении содержимого путем отправки события DOM:
pjax:endondocumentиспользуется многими сайтами на основе pjax, например GitHub,
смотрите как запустить jQuery до и после загрузки pjax?messageonwindowиспользуется, например, поиск Google в браузере Chrome,
смотрите расширение Chrome обнаруживает обновление поиска Googlespfdoneondocumentиспользуется Youtube,
смотрите как определить навигацию по страницам на Youtube и изменить HTML перед отображением страницы?периодическая проверка из DOM через setInterval:
Очевидно, что это будет работать только в тех случаях, когда вы ждете появления определенного элемента, идентифицированного его идентификатором/селектором, и это не позволит вам универсально обнаруживать новое динамически добавленное содержимое, если вы не придумаете какой-то отпечаток существующего содержимого.клоакинг история API внутри вводят дом скрипт:
document.head.appendChild(document.createElement('script')).text = '(' + function() { // injected DOM script is not a content script anymore, // it can modify objects and functions of the page var _pushState = history.pushState; history.pushState = function(state, title, url) { _pushState.call(this, state, title, url); window.dispatchEvent(new CustomEvent('state-changed', {detail: state})); }; // repeat the above for replaceState too } + ')(); this.remove();'; // remove the DOM script element // And here content script listens to our DOM script custom events window.addEventListener('state-changed', function(e) { console.log('History state changed', e.detail, location.hash); doSomething(); });слушать hashchange,popstate события:
window.addEventListener('hashchange', function(e) { console.log('URL hash changed', e); doSomething(); }); window.addEventListener('popstate', function(e) { console.log('State changed', e); doSomething(); });
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.
в дополнение к "сырым" инструментам, предоставленным
MutationObserverAPI, существуют библиотеки "удобства" для работы с мутациями 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