Как использовать MutationObserver?

#javascript #mutation-observers

#javascript #наблюдатели мутаций

Вопрос:

Недавно я наткнулся на эту потрясающую MutationObserver функцию, которая отслеживает изменения в любом элементе dom. Я использовал код, который был показан в сети разработчиков Mozilla, но, похоже, не могу заставить его работать. Это код, который я использовал (ссылка):

    // create an observer instance
var target = document.querySelector('#something');
console.log(target);
var observer = new WebKitMutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      console.log("Success");
        //$('#log').text('input text changed: "'   target.text()   '"');
        //console.log(mutation, mutation.type);
    });    
});
observer.observe(target, { attributes: true, childList: true, characterData: true });
//observer.disconnect(); - to stop observing

// test case
setInterval(function(){
    document.querySelector('#something').innerHTML = Math.random();
},1000);
  

Приведенный выше код, похоже, не работает. Однако, если я изменю тот же код с помощью jQuery, кажется, что все работает просто отлично (демонстрация здесь). Есть ли что-то, чего мне не хватает в документах, или я просто неправильно интерпретирую функцию наблюдателя.

Ответ №1:

Вам нужно subtree: true

http://jsfiddle.net/6Jajs/1/

Внутренний текст обычно является дочерним элементом text() в DOM. Без поддерева он будет наблюдать только за самим элементом.

Возможна путаница, связанная с «CharacterData» (https://developer.mozilla.org/en-US/docs/Web/API/CharacterData ), но, похоже, это относится только к узлам, которые непосредственно содержат текст. DOM структурирован так, что большинство элементов разметки содержат смешанный тип, который необязательно включает дочерний текстовый узел (который, в свою очередь, будет реализовывать CharacterData, но будет дочерним элементом целевого узла).

Комментарии:

1. Спасибо за разъяснение. Я должен провести дополнительные исследования, прежде чем переходить к допросу. 🙂

2. Это также аргумент в пользу использования таких инструментов, как jQuery, даже несмотря на то, что собственный JavaScript и DOM API стали более мощными. Базовый API не скрывает (и IMO не должен) такие технические детали, поэтому есть преимущество в дополнительном уровне абстракции юзабилити.

Ответ №2:

Простой пример:

 <div contentEditable id="myID">MUST EDIT NOW</div>
<script>
let x = new MutationObserver(   function(){ alert('DETECTED'); }   );
x.observe( myID , {subtree:true,characterData:true} );
</script>
  

Смотрите пример в прямом эфире: https://jsfiddle.net/mbo9eLt5 /

Ответ №3:

Для просмотра изменений текста или ввода

использовать

 characterData: true
  

Пример:

 var target = document.querySelector('#text');

var observer = new MutationObserver(function(mutations) {
  
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });
});

var config = {
 
  characterData: true,
        subtree: true,

};

observer.observe(target, config);

// otherwise
observer.disconnect();
observer.observe(target, config);  
 <div id="text" contenteditable="true">characterData:true</div>  

Для просмотра дочерних элементов или добавления текста или вставки Dom

 childList:true
  

Пример:

 var target = document.querySelector('#text');

var observer = new MutationObserver(function(mutations) {
  
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });
});

var config = {

  childList: true,
      subtree: true,
      };

observer.observe(target, config);

// otherwise
observer.disconnect();
observer.observe(target, config);  
 <div id="text" contenteditable="true">characterData:true</div>

<button onclick="testappend();
function testappend(){
document.getElementById('text').append('tesxt')
}">append</button>  

Для просмотра атрибутов dom

    attributes: true
  

Пример

 var target = document.querySelector('#text');

var observer = new MutationObserver(function(mutations) {
  
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });
});

var config = {
 
  characterData: true,
   attributes: true,
 
};

observer.observe(target, config);

// otherwise
observer.disconnect();
observer.observe(target, config);  
 <div id="text" contenteditable="true">characterData:true</div>

<button onclick="testappend();
function testappend(){
document.getElementById('text').classList.add('tesxt')
}">add class</button>

<button onclick="setat();
function setat(){
document.getElementById('text').setAttribute('data-prop','text')
}">set attribute</button>  

 attribute old value
  

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit/attributeOldValue