Страницы

Поиск по вопросам

пятница, 29 ноября 2019 г.

Событие изменения содержимого тега

#javascript #html #dom #события


Есть ли событие в JavaScript, возникающее при изменении содержимого тега? Например,
при изменении содержимого 


Ответы

Ответ 1



Прослушать можно любой тег. Для прослушки изменения в поддереве нужно использовать DOMSubtreeModified. В примере ниже есть 2 параграфа

- demo1 и demo2. На document установлено событие клика - такое, что при клике на любой участок страницы, содержимое demo1 меняется на demo1 -> Hello World!. Другой слушатель ждёт изменение в поддереве demo1, и когда событие наступает, содержимое demo2 меняется на demo1 Changed! document.getElementById("demo1").addEventListener("DOMSubtreeModified", function() { document.getElementById("demo2").innerHTML = "demo1 Changed!" }); document.addEventListener("click", function() { document.getElementById("demo1").innerHTML = "demo1 -> Hello World!"; });

demo1



Ответ 2



Введение Была попытка сделать события на изменения элементов в DOM, да всплыла, уж очень оно сильно влияло на производительность. Называются они в литературе Mutation events: DOMAttrModified - если изменился атрибут у элемента DOM; DOMAttributeNameChanged - если изменилось имя атрибута у элемента DOM; DOMCharacterDataModified - если изменился какой-либо текст, будь то обычный 'text node' или простой комментарий у элемента DOM; DOMElementNameChanged - если изменилось имя у элемента DOM; DOMNodeInserted - если у элемента DOM произошла вставка нового элемента; DOMNodeInsertedIntoDocument - если произошла вставка нового элемента в document; DOMNodeRemoved - если у элемента DOM произошло удаление какого-либо элемента; DOMNodeRemovedFromDocument - если произошло удаление какого-либо элемента в document; DOMSubtreeModified - если произошло какое-либо изменение в document. Все они 'deprecated' и крайне не рекомендуются к использованию. Тем более, далеко не факт, что они будут работать в Вашем браузере, а проверить наличие этого события не такая уж тривиальная задача, так как атрибутов у элементов с одноименным названием нет. Альтернатива 0, для внимательных Как альтернатива примем тот факт, что всегда можно создавать свои события, всплывающие при изменениях. То есть можно сделать вот так: придумываем название события, например, DOM:changed; создаем функции-обработчики и подписываем их на эти события; находим все функции, которые могут потенциально изменить DOM; при любых, интересующих Вас, изменениях в DOM в этих функциях вызываем пользовательское событие. У этого метода потрясающие возможности в управлении уведомлениями, всегда можно выбрать, что вызывает событие, аккуратно их фильтровать и создавать удобную атмосферу для их вызова. Но всегда есть возможность забыть добавить это в код, надо быть внимательным и тщательно всё затестировать. Альтернатива 1, простая Можно придумать ещё два способа это сделать. Первый, в лоб, не совсем корректный, но имеет место жить на небольших данных, далее я расскажу о правильном: берём эталонный .innerHTML у Вашего div'а и сохраняем его куда угодно, например, в sessionStorage каждые n секунд сравниваем текущий .innerHTML с эталонным, если не равны, значит произошли какие-либо изменения и вызываем callback. Можно красиво обернуть в промис. Можно даже вместо вызова callback вызывать свое пользовательское событие. Способ хорош, быстр, если div не многокилометровый. Самое главное - весьма и весьма кроссбраузерный, заработает даже в ie7. Но вот если div будет большим, то это может вызывать тормоза. Альтернатива 2, то, что надо Второй способ правильный. После неудачной попытки со специальными событиями, придумали, оно действительно работает в хороших браузерах, MutationObserver(), а если нет, то его полифилл. Как его использовать? А вот так. Сначала создадим объект MutationObserver: var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.dir(mutation); //объект с изменениями }); }); В данном случае mutations - массив MutationRecord, каждый элемент которого содержит следующие поля: type - все измененные атрибуты или characterData (текстовый элемент или комментарий) или childList в зависимости от типа мутации; target - элемент дерева, в котором произошло изменение; addedNodes - NodeList, содержащий добавленные элементы дерева, логично, что он будет пуст (*.length == 0), если таких не будет. removedNodes - NodeList, содержащий удаленные элементы дерева, он тоже будет пуст, если таких иметься не будет; previousSibling - предыдущий сосед по дереву добавленного или удаленного элемента или null; nextSibling - следующий сосед по дереву добавленного или удаленного элемента или null; attributeName - имя измененного атрибута или null; oldValue - старые значения, до изменения, но в случае, если изменение произошло в childList - null. Затем, чтобы эта прелесть заработала, скажем интерпретатору "начать слежение": observer.observe( elem, { childList: true, attributes: true, subtree: true, characterData: true, attributeOldValue: true, characterDataOldValue: true, attributeFilter: true } ); Первым аргументом мы передаем объект DOM, за которым нужно следить, вторым - то, как мы будем следить: childList - следим за вставкой/удалением элементов в childList; attributes - следим за изменением атрибутов characterData - следим за изменением characterData (текстовые элементы или комментарии) attributeOldValue - запоминаем значение атрибута до изменения characterDataOldValue - запоминаем значение characterData до изменения attributeFilter - Array тех атрибутов, за которыми будем следить Для того, чтобы остановить слежение можно вызвать метод observer.disconnect();. Предостережение Не советую изменять элемент DOM, за которым мы следим, может получиться весьма пикантная ситуация. Забытая на потом последняя альтернатива Стоит упомянуть, что существует стандартное событие, полностью кроссбраузерное и работающее - onchange. Работает оно в элементах ,