Какой тип события я должен зарегистрировать в элементе, чтобы отслеживать добавление подэлементов - PullRequest
0 голосов
/ 06 мая 2020

Я ищу способ узнать, что элемент был добавлен в мой div.

Элемент стиля добавлен сторонним компонентом, и я просто знаю, в какой элемент будет добавлен. Я могу отследить это с помощью DevTools с точкой останова DOM на моем div, но, вероятно, это внутренняя функция Chrome.

Есть ли способ, как прослушивать запущенное событие, связанное с прямым изменением поддерева? Примерно так:

document.getElementById("my-div").addEventListener("subtree-modification", function(event) { ... my event handler });

Я нашел информацию о MutationObserver в do c. Это путь вперед? Можете привести пример?

Ответы [ 3 ]

2 голосов
/ 06 мая 2020

MutationObserver будет работать. (Напротив, события мутации через addEventListener устарели и медленны, лучше их избегать.) Например:

console.log('script start');
const myDiv = document.getElementById("my-div");

new MutationObserver((mutations, observer) => {
  console.log('Change observed');
  // Once the change is seen, don't need the observer anymore
  observer.disconnect();
})
  .observe(myDiv, { childList: true });


setTimeout(() => {
  myDiv.appendChild(document.createElement('span')).textContent = 'span content';
}, 3000);
<div id="my-div">my div </div>

childList: true будет следить за изменениями в любых прямых потомках наблюдаемого элемента. Если вы хотите следить за изменениями любого потомка , используйте также subtree: true:

{ childList: true, subtree: true }

Но глубокие наблюдатели обходятся дорого - не забудьте удалить их, когда они выполнят то, что вы нужно.

0 голосов
/ 06 мая 2020

Вот пример использования, это просто MutationObserver , которые следят за удалением / добавлением элементов, обратите внимание, что я использовал setTimeout для удаления <li> элемента через 1 секунду и еще один для добавления элемента через 2 секунды:

function callback(mutationList, observer) {
  mutationList.forEach((mutation) => {
    switch (mutation.type) {
      case "childList":
        if (mutation.removedNodes.length) {
          console.log("removed element here");
        }

        if (mutation.addedNodes.length) {
          console.log("Added element here");
        }
        break;
    }
  });
}

var targetNode = document.querySelector("#someElement");
var observerOptions = {
  childList: true,
  attributes: true,
  subtree: true, //Omit or set to false to observe only changes to the parent node.
};

var observer = new MutationObserver(callback);
observer.observe(targetNode, observerOptions);

setTimeout(function () {
  document.getElementById("el2").remove();
}, 1500);

setTimeout(function () {
  let newLi = document.createElement("li");
  newLi.innerHTML = "new Li";
  document.getElementById("ulElm").appendChild(newLi);
}, 2000);
<div id="someElement">
  <ul id="ulElm">
    <li> element 1 </li>
    <li id="el2"> element 2 </li>
    <li> element 3 </li>
    <li> element 4 </li>
  </ul>
</div>
0 голосов
/ 06 мая 2020

Как вы упомянули, это можно сделать с помощью MutationObserver:

// Select the node that will be observed for mutations:
const targetNode = document.getElementById('target');

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

// Create an observer instance linked to the callback function
const observer = new MutationObserver((mutationsList, observer) => {
  mutationsList.forEach((mutation) => {
    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.');
    }
  });
});

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

// Modify the observer element to see this in action:
targetNode.innerText = 'Updated content.';
targetNode.setAttribute('data-foo', 'bar');
targetNode.removeAttribute('data-foo');
<div id="target">Initial content.</div>
...