父项更改时的MutationObserver

时间:2019-06-03 12:41:43

标签: javascript html mutation-observers

有没有一种方法可以检测到元素的父元素何时发生更改(即,当元素从null更改为!null时,即元素最初添加到DOM时),使用{{ 1}}?我找不到任何文档说明如何实现此目标。

我正在以编程方式使用MutationObserver创建元素。我从函数返回创建的元素,但想从函数内部创建一个侦听器,以在元素最终添加到DOM时做出反应,而又不知道 where 或< em>哪个父对象。


老实说,我不太确定该怎么说。

document.createElement()

我看不出要理解它有什么难之处或为什么要关闭它。

2 个答案:

答案 0 :(得分:1)

您可以收听DOMNodeInserted事件并比较元素ID。

  

通知: 该事件被标记为已取消,并且可能会在不久的将来停止在现代浏览器中运行   未来。

let container = document.getElementById('container');
let button = document.getElementById('button');

document.body.addEventListener('DOMNodeInserted', function(event) {
  if (event.originalTarget.id == button.id) {
    console.log('Parent changed to: ' + event.originalTarget.parentElement.id);
  }
});

button.addEventListener('click', function(event) {
  container.appendChild(button);
});
#container {
  width: 140px;
  height: 24px;
  margin: 10px;
  border: 2px dashed #c0a;
}
<div id="container"></div>
<button id="button">append to container</button>

答案 1 :(得分:1)

一种简单而精致的方法是猴子补丁Node.prototype.appendChild(必要时还有Element.prototype.appendElement.prototype.insertAdjacentElementNode.prototype.insertBefore)来监视何时将元素添加到DOM:

const elementsToWatch = new Set();
const { appendChild } = Node.prototype;
Node.prototype.appendChild = function(childToAppend) {
  if (elementsToWatch.has(childToAppend)) {
    console.log('Watched child appended!');
    elementsToWatch.delete(childToAppend);
  }
  return appendChild.call(this, childToAppend);
};



button.addEventListener('click', () => {
  console.log('Element created...');
  const div = document.createElement('div');
  elementsToWatch.add(div);
  setTimeout(() => {
    console.log('About to append element...');
    container.appendChild(div);
  }, 1000);
});
<button id="button">Append something after 1000ms</button>
<div id="container"></div>

但是,将内置原型静音通常不是一个好主意。

另一种选择是对整个文档使用MutationObserver,但这很可能会导致大量频繁出现突变的大页面的激活回调,这可能是不希望的:

const elementsToWatch = [];
new MutationObserver(() => {
  // instead of the below, another option is to iterate over elements
  // observed by the MutationObserver
  // which could be more efficient, depending on how often
  // other elements are added to the page
  const root = document.documentElement; // returns the <html> element
  const indexOfElementThatWasJustAdded = elementsToWatch.findIndex(
    elm => root.contains(elm)
  );
  // instead of the above, could also use `elm.isConnected()` on newer browsers
  
  // if an appended node, if it has a parent,
  // will always be in the DOM,
  // instead of `root.contains(elm)`, can use `elm.parentElement`

  if (indexOfElementThatWasJustAdded === -1) {
    return;
  }
  elementsToWatch.splice(indexOfElementThatWasJustAdded, 1);
  console.log('Observed an appended element!');
}).observe(document.body, { childList: true, subtree: true });


button.addEventListener('click', () => {
  console.log('Element created...');
  const div = document.createElement('div');
  div.textContent = 'foo';
  elementsToWatch.push(div);
  setTimeout(() => {
    console.log('About to append element...');
    container.appendChild(div);
  }, 1000);
});
<button id="button">Append something after 1000ms</button>
<div id="container"></div>