Событие jQuery: обнаружение изменений в HTML / тексте div

216

У меня есть div, содержимое которого постоянно меняется, будь то ajax requests, jquery functions, blur т.д. И т.д.

Есть ли способ, которым я могу обнаружить любые изменения в моем div в любой момент времени?

Я не хочу использовать интервалы или значение по умолчанию.

Нечто подобное сделало бы

$('mydiv').contentchanged() {
 alert('changed')
}
  • 5
    Возможный дубликат: stackoverflow.com/questions/10328102/…
  • 14
    @Rob Это связывает событие keypress с contenteditable элементом <div> . Я не уверен, что решения там применимы к этому. Они определенно не поймут никаких программных изменений в содержании элемента.
Теги:

11 ответов

313

Если вы не хотите использовать таймер и проверить innerHTML, вы можете попробовать это событие

$('mydiv').bind("DOMSubtreeModified",function(){
  alert('changed');
});

Более подробная информация и данные о поддержке браузера находятся здесь.

Внимание: в новых версиях jQuery bind() устарел, поэтому вместо него следует использовать on():

$("body").on('DOMSubtreeModified', "mydiv", function() {
    alert('changed');
});
  • 13
    Имейте в виду, что DOMSubtreeModified не поддерживается в IE8 (и ниже).
  • 53
    это событие устарело w3.org/TR/DOM-Level-3-Events/#glossary-deprecated
Показать ещё 8 комментариев
37

Вы можете попробовать это

$('.myDiv').bind('DOMNodeInserted DOMNodeRemoved', function() {

});

но это может не работать в Internet Explorer, не проверял его

  • 8
    Исключено: developer.mozilla.org/en-US/docs/Web/Guide/Events/… Вместо этого используйте: developer.mozilla.org/en-US/docs/Web/API/MutationObserver
  • 2
    ПРИМЕЧАНИЕ !: если вы используете это для триггера, и на страницу будет внесено много изменений - она будет запускать вашу функцию X раз (возможно, даже X = 1000 или более), что может быть очень неэффективно. Одно простое решение - определить «работающий» логический var, который будет ... if (running == true) {return} ... без запуска вашего кода, если он уже запущен. Установите running = true сразу после логики if, и running = false до выхода из функции. Вы также можете использовать таймер, чтобы ограничить вашу функцию, чтобы иметь возможность запускаться каждые X секунд. работает = истина; SetTimeout (функция () {работает = ложь}, 5000); (или что-то лучше)
Показать ещё 4 комментария
35

Поскольку $("#selector").bind() устарел, вы должны использовать:

$("body").on('DOMSubtreeModified', "#selector", function() {
    // code here
});
  • 1
    Это был дифференцирующий фактор, дополнительный # указывающий, что символ должен идти перед селектором.
  • 0
    Этот метод все еще работает
25

Вы ищете MutationObserver или События мутации. Ни одна из них не поддерживается повсюду и не слишком ласкает мир разработчиков.

Если вы знаете (и можете убедиться, что) размер div изменится, вы можете использовать событие изменения размера кроссбраузера.

  • 1
    Это тот самый. В частности, DOMSubtreeModified . Может оказаться полезной библиотека итоговых мутаций и этот список событий дерева DOM .
  • 1
    это событие устарело developer.mozilla.org/en-US/docs/Web/Guide/Events/…
Показать ещё 1 комментарий
20

Использование Javascript MutationObserver

  //More Details https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
 // select the target node
var target = document.querySelector('mydiv')
// create an observer instance
var observer = new MutationObserver(function(mutations) {
  console.log($('mydiv').text());   
});
// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };
// pass in the target node, as well as the observer options
observer.observe(target, config);
  • 2
    Это правильный ответ, так как теперь он более предпочтителен, чем использование DOMSubtreeModified.
17

Следующий код работает для меня.

$("body").on('DOMSubtreeModified', "mydiv", function() {
    alert('changed');
});

Надеюсь, это поможет кому-то:)

  • 0
    Ответ тот же, что и у @Artley
  • 0
    @ Чёрный Спасибо! Я только что проверил ответ Артли. Я позабочусь об этом в следующий раз.
17

Нет встроенного решения этой проблемы, это проблема с вашим шаблоном проектирования и кодирования.

Вы можете использовать шаблон издателя/подписчика. Для этого вы можете использовать специальные события jQuery или собственный механизм событий.

Во-первых,

function changeHtml(selector, html) {
    var elem = $(selector);
    jQuery.event.trigger('htmlchanging', { elements: elem, content: { current: elem.html(), pending: html} });
    elem.html(html);
    jQuery.event.trigger('htmlchanged', { elements: elem, content: html });
}

Теперь вы можете подписаться на события divhtmlchanging/divhtmlchanged, как показано ниже,

$(document).bind('htmlchanging', function (e, data) {
    //your before changing html, logic goes here
});

$(document).bind('htmlchanged', function (e, data) {
    //your after changed html, logic goes here
});

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

Вы должны изменить свой div html следующим образом:

changeHtml('#mydiv', '<p>test content</p>');

А также вы можете использовать это для любых элементов html, кроме элемента ввода. В любом случае вы можете изменить это для использования с любым элементом (ами).

  • 0
    Чтобы наблюдать за изменениями в конкретном элементе и воздействовать на них, просто измените функцию changeHtml, чтобы использовать «elem.trigger (...)» вместо «jQuery.event.trigger (...)», а затем привязать к элементу следующим образом: $ ('# my_element_id'). on ('htmlchanged', функция (e, data) {...}
  • 8
    «Это проблема с вашим дизайном и шаблоном кодирования», что делать, если вы включаете сторонние скрипты, поэтому не можете контролировать их исходный код? но вам нужно обнаружить их изменения в одном div?
Показать ещё 1 комментарий
4

Используйте MutationObserver, как показано в этом фрагменте, предоставленном Mozilla, и адаптирован из этого поста в блоге.

Кроме того, вы можете использовать пример JQuery, показанный в этой ссылке

Chrome 18+, Firefox 14+, IE 11+, Safari 6+

// Select the node that will be observed for mutations
var targetNode = document.getElementById('some-id');

// Options for the observer (which mutations to observe)
var config = { attributes: true, childList: true };

// Callback function to execute when mutations are observed
var callback = function(mutationsList) {
    for(var mutation of mutationsList) {
        if (mutation.type == 'childList') {
            console.log('A child node has been added or removed.');
        }
        else if (mutation.type == 'attributes') {
            console.log('The ' + mutation.attributeName + ' attribute was modified.');
        }
    }
};

// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(targetNode, config);

// Later, you can stop observing
observer.disconnect();
3

Вы можете сохранить старый innerHTML div в переменной. Установите интервал, чтобы проверить, совпадает ли старый контент с текущим контентом. Когда это не так, сделайте что-нибудь.

1

Попробуйте MutationObserver:

поддержка браузера: http://caniuse.com/#feat=mutationobserver

<html>
  <!-- example from Microsoft https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/dev-guide/dom/mutation-observers/ -->

  <head>
    </head>
  <body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script type="text/javascript">
      // Inspect the array of MutationRecord objects to identify the nature of the change
function mutationObjectCallback(mutationRecordsList) {
  console.log("mutationObjectCallback invoked.");

  mutationRecordsList.forEach(function(mutationRecord) {
    console.log("Type of mutation: " + mutationRecord.type);
    if ("attributes" === mutationRecord.type) {
      console.log("Old attribute value: " + mutationRecord.oldValue);
    }
  });
}
      
// Create an observer object and assign a callback function
var observerObject = new MutationObserver(mutationObjectCallback);

      // the target to watch, this could be #yourUniqueDiv 
      // we use the body to watch for changes
var targetObject = document.body; 
      
// Register the target node to observe and specify which DOM changes to watch
      
      
observerObject.observe(targetObject, { 
  attributes: true,
  attributeFilter: ["id", "dir"],
  attributeOldValue: true,
  childList: true
});

// This will invoke the mutationObjectCallback function (but only after all script in this
// scope has run). For now, it simply queues a MutationRecord object with the change information
targetObject.appendChild(document.createElement('div'));

// Now a second MutationRecord object will be added, this time for an attribute change
targetObject.dir = 'rtl';


      </script>
    </body>
  </html>
0

Добавление некоторого содержимого в div, будь то через jQuery или через DOM-API напрямую, по умолчанию используется функция .appendChild(). Что вы можете сделать, это переопределить функцию .appendChild() текущего объекта и реализовать в ней наблюдателя. Теперь, переопределив нашу функцию .appendChild(), нам нужно взять эту функцию из другого объекта, чтобы иметь возможность добавлять содержимое. Поэтому мы вызываем .appendChild() другого div, чтобы, наконец, добавить содержимое. Конечно, это также относится к .removeChild().

var obj = document.getElementById("mydiv");
    obj.appendChild = function(node) {
        alert("changed!");

        // call the .appendChild() function of some other div
        // and pass the current (this) to let the function affect it.
        document.createElement("div").appendChild.call(this, node);
        }
    };

Здесь вы можете найти наивный пример. Думаю, вы можете продлить его самостоятельно. http://jsfiddle.net/RKLmA/31/

Кстати: это показывает, что JavaScript соответствует принципу OpenClosed.:)

  • 0
    Он не работает с append child ... На самом деле я изменяю его HTML через другие функции.
  • 0
    Затем переопределите другие функции таким же образом.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню