【问题标题】:MutationObserver and querySelectorAllMutationObserver 和 querySelectorAll
【发布时间】:2017-12-10 05:17:11
【问题描述】:

我目前正在学习 Javascript,其中一章是“Mutation Observer”。我正在尝试创建一个简单的函数来检测是否将新 div 添加到页面并将其显示在控制台中。但是,我收到了这条消息,我很难找到解决这个错误的方法。如果有人能向我解释我做错了什么,我将不胜感激。提前谢谢!

未捕获的类型错误:无法在“MutationObserver”上执行“观察”:参数 1 不是“节点”类型。

到目前为止,这是我写的代码:

document.getElementById("Button").onclick = function(){
  var Add = document.createElement('div');
    Add.setAttribute("class", "Alpha");
    Add.appendChild(document.createTextNode("Test"));
    document.getElementById('Frame').appendChild(Add);
};

var Divs = document.querySelectorAll("div");
var Observer = new MutationObserver(function(mutations){
  mutations.forEach(function(mutation){
    for(var i = 0; i <= mutation.addedNodes.length; i++){
      if(!(mutation.addedNodes[i] == null)){
        console.log(mutation.addedNodes[i].innerHTML);
      }
    }
  });
});
Observer.observe(Divs, {childList: true, subtree:true});
.Alpha{
  color:red;
}
<button id="Button">Generate a new div</button>
<div id="Frame"></div>

【问题讨论】:

  • 方法observe 在第一个参数中采用单个节点,而不是节点集合。

标签: javascript mutation-observers mutation mutation-events


【解决方案1】:

错误消息中解释了该问题。 observe 函数需要 Node,但您正在分配 querySelectorAll 查找的返回值,它实际上返回 NodeList(所以一个或多个节点)。即使它什么也没找到,它也会返回一个空的NodeList 并且仍然是无效的。

在您的实例中,您似乎将项目推入 ID 为 Frame 的 DIV,因此我们会将 MutationObserver 附加到该 DIV 上,并注意其子项的任何更改。最后,我们会将任何更改的节点推送到一个数组中,并在控制台记录内容,以便您查看它正在捕获的内容,

var target = document.getElementById('Frame');
var insertedNodes = [];
var Observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        for(var i = 0; i < mutation.addedNodes.length; i++) {
            insertedNodes.push(mutation.addedNodes[i]);
        }
    });
});

Observer.observe(target, {
    childList: true,
    subtree:true
});

console.log(insertedNodes);

【讨论】:

  • 非常感谢您的快速响应。它工作得很好。但是,我有以下几个问题。 1)如果我想观察一个随机的 div 元素是否被添加到 DOM 中怎么办?我假设您必须将var target=document.getElementById('Frame') 更改为var target=document.body,但是您不仅会观察div 元素,还会观察span、p、a 等。 2)有没有办法粉碎一个里面有子元素的div?我尝试创建第二个for 循环,但这次使用insertedNodes.childNodes.length;,但它不返回任何结果。 JsFiddle
  • 您的 jsfiddle 仅枚举每个插入节点的直接子节点。您可能想改用 .getElementsByTagName('div') 。但请注意文本节点,因为它们没有任何子节点,因此请先检查:例如if (node.children &amp;&amp; node.children.length)
  • @wOxxOm 这是我最初的想法,但不幸的是,当我使用document.getElementsByTagName('div'); 时,它再次给了我同样的错误Uncaught TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'.,我又回到了原点。正如 Dwayne 指出的那样,document.querySelectorAll("div");document.getElementsByTagName('div') 都返回了一个非活动的 NodeList 值。这就是我改用document.body; 的原因。
  • 不,我不是这个意思。您的 jsfiddle 在观察者回调中检查 childNodes,这就是我所说的。
  • @wOxxOm,你的意思是类似的吗? - JsFiddle 但是,它只需要父级,并且由于某种原因会跳过 div 内的子级。你能告诉我我的逻辑错误在哪里吗?提前谢谢你。
猜你喜欢
  • 2019-10-29
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-15
  • 2016-05-19
相关资源
最近更新 更多