使用 MutationObserver 时,DOM 中似乎不存在 ChildNode

发布于 2025-01-14 08:07:30 字数 1340 浏览 6 评论 0原文

我正在尝试使用 MutationObserver 来观察 DOM 中的变化,但似乎我无法访问“大”子节点。我已经使用 subtree 和 childList 值配置了观察者。据我了解,使用 MutationObserver 不可能获取添加的 childList 或更改的整个 DOM 树,它所做的只是观察更改。相反,您应该使用 getElementById。

我尝试在观察到更改后使用 getElementById 在 DOM 中查找相关的“父”节点,然后抓取所有子节点。尽管我仍然没有得到子节点的命中。

我假设“父”节点首先插入到 DOM 上,然后将子节点插入到“父”节点上,尽管由于某种原因这些事件不会在观察者中触发。

我怀疑我可能需要在观察变化时更新 MutationObserver 的目标,然后不断使用 getElementById 并爬取这些节点。

知道为什么这些子节点不可观察,和/或如何解决这个问题吗?

此致。

MutationObserver 的代码

function createObserver() {
    const documentBody = document.body;

    // callback function to execute when mutations are observed
    const observer = new MutationObserver(mutationRecords => {
        let addedNodes = []

        for (const mut of mutationRecords) {

            let arr = Array.prototype.slice.call(mut.addedNodes)
            arr = arr.filter(node => popupTagNames.includes(node.tagName)); // Keep only selected tags

            if (arr.length == 0) return; // don't keep empty

            addedNodes = addedNodes.concat(arr)

            let el = document.getElementById(addedNodes[0].id);

            // Crawler
            inspectNode(el)
        }


    })

    const config = { attributes: true, childList: true, subtree: true, characterData: true }
    observer.observe(documentBody, config)
}

I am trying to use MutationObserver to observe changes in the DOM but it seems like I can't access the "grand"-children nodes. I have configured the observer with subtree and childList values. As I understand, it is not possible to get the entire DOM-tree of added childLists or changes with the MutationObserver, all it does is observe the changes. Instead you are supposed to use getElementById.

I've tried using getElementById to find the relevant "parent"-node in the DOM after the change is observed, and then crawl all the childNodes. Although I still get no hits on the childNodes.

I assume the "parent"-node is inserted onto the DOM first, and the childNodes are then inserted on to the "parent"-node after the fact, though these events are not triggered in the observer for some reason.

I suspect I might need to update the target of the MutationObserver as I observe the changes, and then continuously use getElementById and crawl these nodes.

Any idea on why these childNodes are not observable, and/or how to approach the solution to this?

Best regards.

Code to MutationObserver

function createObserver() {
    const documentBody = document.body;

    // callback function to execute when mutations are observed
    const observer = new MutationObserver(mutationRecords => {
        let addedNodes = []

        for (const mut of mutationRecords) {

            let arr = Array.prototype.slice.call(mut.addedNodes)
            arr = arr.filter(node => popupTagNames.includes(node.tagName)); // Keep only selected tags

            if (arr.length == 0) return; // don't keep empty

            addedNodes = addedNodes.concat(arr)

            let el = document.getElementById(addedNodes[0].id);

            // Crawler
            inspectNode(el)
        }


    })

    const config = { attributes: true, childList: true, subtree: true, characterData: true }
    observer.observe(documentBody, config)
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

若有似无的小暗淡 2025-01-21 08:07:30

让我们通过记录属于 #qc-cmp2-container 元素的添加节点来进行调查:

new MutationObserver(mutations => {
  const parent = document.getElementById('qc-cmp2-container');
  if (parent) console.log(...mutations.flatMap(m =>
    [...m.addedNodes].filter(n => parent.contains(n)).map(n => n.cloneNode(true))));
}).observe(document, {subtree: true, childList: true});

我们将看到几个单独的调用:

  1. 主 #qc-cmp2-container 及其空子元素
  2. 包含许多子元素和文本的内部 div
  3. 两个添加额外的内部元素

最节省资源的解决方案是使用超快速 getElementById 检查等待父级,然后切换到观察父级:

function waitForId(id, callback) {
  let el = document.getElementById(id);
  if (el) {
    callback(el);
  } else {
    new MutationObserver((mutations, observer) => {
      el = document.getElementById(id);
      if (el) {
        observer.disconnect();
        callback(el);
      }
    }).observe(document, { subtree: true, childList: true });
  }
}

waitForId('qc-cmp2-container', parent => {
  new MutationObserver((mutations, observer) => {
    // do something
  }).observe(parent, { subtree: true, childList: true });
});

Let's investigate by logging the added nodes that belong to #qc-cmp2-container element:

new MutationObserver(mutations => {
  const parent = document.getElementById('qc-cmp2-container');
  if (parent) console.log(...mutations.flatMap(m =>
    [...m.addedNodes].filter(n => parent.contains(n)).map(n => n.cloneNode(true))));
}).observe(document, {subtree: true, childList: true});

We'll see several separate calls:

  1. The main #qc-cmp2-container and its empty child
  2. An inner div with a lot of child elements and text
  3. Two additional inner elements are added

The most resource-effective solution is to wait for the parent using the super fast getElementById check and then switch to observing the parent:

function waitForId(id, callback) {
  let el = document.getElementById(id);
  if (el) {
    callback(el);
  } else {
    new MutationObserver((mutations, observer) => {
      el = document.getElementById(id);
      if (el) {
        observer.disconnect();
        callback(el);
      }
    }).observe(document, { subtree: true, childList: true });
  }
}

waitForId('qc-cmp2-container', parent => {
  new MutationObserver((mutations, observer) => {
    // do something
  }).observe(parent, { subtree: true, childList: true });
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文