为什么MutationObserver会为childList两次触发而不会为characterData两次触发? [英] Why does MutationObserver fire twice for childList but never for characterData?

查看:190
本文介绍了为什么MutationObserver会为childList两次触发而不会为characterData两次触发?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的 MutationObserver 设置作为测试。 HTML具有 span ,其文本内容每秒更新一次(对于消息,则为 div ):

I have a simple MutationObserver setup as a test. The HTML has a span whose text content gets updated once per second (and a div for messages):

<span class="tester"></span>
<div id="msg"></div>

MutationObserver设置为监视 .tester 并在观察到更改时将文本写入 #msg div 。同时, setInterval()每秒运行一次以更改 .tester

The MutationObserver is set to watch .tester and writes text to the #msg div when it observes a change. Meanwhile, a setInterval() runs once/second to change the text in .tester:

var target = document.querySelector('.tester');

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
    $('#msg').append(mutation.type+"<br/>")
    setTimeout(function() { $('#msg').text(''); }, 500);
  });    
});

var config = { attributes: true, childList: true, characterData: true };
observer.observe(target, config);

setInterval(function() {
  $('#msg').text('');
  $('.tester').text("update: "+Math.random())
}, 1000);

我希望这段代码每秒打印一次 characterData 具有的代码改变了。根据 Mozilla的MutationObserver文档,它对characterData表示:如果发生突变,则设置为true观察目标数据。相反,我没有看到characterData突变,但是 do 每秒看到两个childList突变。

I would expect this code to print once per second that the characterData has changed. According to Mozilla's docs for MutationObserver, it says about characterData: "Set to true if mutations to target's data are to be observed." Instead, I see no characterData mutations but do see two childList mutations every second.

为什么我没有看到任何characterData突变,为什么我看到两个 childList突变吗?

Why am I not seeing any characterData mutations, and why am I seeing two childList mutations?

这是一个 CodePen

推荐答案

原因是Jeremy Banks说:使用jQuery的 text(),它将删除所有文本节点,然后添加新的文本节点。这不是对字符数据的更改,而是对 childList 的更改:删除那里的节点并用新的节点替换。

The reason is as Jeremy Banks said: When you use jQuery's text(), it removes all the text nodes and then adds in new ones. That's not a change to character data, it's a change to the childList: Removing the node that's there and replacing it with a new one.

要查看字符数据的更改,必须修改现有文本节点的 nodeValue 观察子树修改:

To see a change to character data, you have to modify the existing text node's nodeValue, and observe subtree modifications:

var target = document.querySelector('.tester');

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log(mutation.type);
        $('#msg').append(mutation.type+"<br/>")
        setTimeout(function() { $('#msg').text(''); }, 500);
    });    
});

var config = {
    attributes: true,
    childList: true,
    characterData: true,
    subtree: true                   // <=== Change, added subtree
};
observer.observe(target, config);

var timer = setInterval(function() {
    $('#msg').text('');
    // Change --VVVVV modifying the existing child node
    $('.tester')[0].firstChild.nodeValue = "updated" + Math.random();
}, 1000);

// Stop after 10 seconds
setTimeout(function() {
    clearInterval(timer);
}, 10000);

<span class="tester">x</span><!-- Change, added a starting child node -->
<div id="msg"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

问您为什么有两个 <是code> childList 突变,是的,我认为您是对的:他们要删除孩子,然后添加一个新孩子。如果我们使用 replaceChild 方法,我们只看到一个突变:

Re your question about why there are two childList mutations, yes I think you're right: They're removing the child, then adding a new one. If we use the replaceChild method, we see only a single mutation:

var target = document.querySelector('.tester');

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log(mutation.type);
        $('#msg').append(mutation.type+"<br/>")
        setTimeout(function() { $('#msg').text(''); }, 500);
    });    
});

var config = {
    attributes: true,
    childList: true,
    characterData: true,
    subtree: true                   // <=== Change, added subtree
};
observer.observe(target, config);

var timer = setInterval(function() {
    $('#msg').text('');
    // Change --VVVVV modifying the existing child node
    var text = document.createTextNode("updated" + Math.random());
    var parent = $('.tester')[0];
    parent.replaceChild(text, parent.firstChild);
}, 1000);

// Stop after 10 seconds
setTimeout(function() {
    clearInterval(timer);
}, 10000);

<span class="tester">x</span><!-- Change, added a starting child node -->
<div id="msg"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

这篇关于为什么MutationObserver会为childList两次触发而不会为characterData两次触发?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆