为什么 MutationObserver 会为 childList 触发两次而不会为 characterData 触发?
Why does MutationObserver fire twice for childList but never for characterData?
我有一个简单的 MutationObserver
设置作为测试。 HTML 有一个 span
,其文本内容每秒更新一次(还有一个 div
用于消息):
<span class="tester"></span>
<div id="msg"></div>
MutationObserver 设置为观察 .tester
并在观察到变化时将文本写入 #msg
div
。同时,setInterval()
运行 once/second 来更改 .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's docs for MutationObserver,它说的是 characterData:"Set to true if mutations to target's data are to be observed." 相反,我没有看到 characterData 突变,但是 do 每秒看到两个 childList 突变。
为什么我没有看到任何 characterData 突变,为什么我看到 两个 childList 突变?
这是 CodePen 的工作示例。
原因如:当你使用jQuery的text()
时,它会删除所有的文本节点,然后添加新的。这不是对字符数据的更改,而是对 childList
的更改:删除那里的节点并用新节点替换它。
要查看对字符数据的更改,您必须修改 现有 文本节点的 nodeValue
、 和 观察 subtree
修改:
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>
关于为什么有 两个 childList
突变的问题,是的,我认为你是对的:他们正在移除 child,然后添加一个新的。如果我们使用 replaceChild
method,我们只会看到一个突变:
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
设置作为测试。 HTML 有一个 span
,其文本内容每秒更新一次(还有一个 div
用于消息):
<span class="tester"></span>
<div id="msg"></div>
MutationObserver 设置为观察 .tester
并在观察到变化时将文本写入 #msg
div
。同时,setInterval()
运行 once/second 来更改 .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's docs for MutationObserver,它说的是 characterData:"Set to true if mutations to target's data are to be observed." 相反,我没有看到 characterData 突变,但是 do 每秒看到两个 childList 突变。
为什么我没有看到任何 characterData 突变,为什么我看到 两个 childList 突变?
这是 CodePen 的工作示例。
原因如text()
时,它会删除所有的文本节点,然后添加新的。这不是对字符数据的更改,而是对 childList
的更改:删除那里的节点并用新节点替换它。
要查看对字符数据的更改,您必须修改 现有 文本节点的 nodeValue
、 和 观察 subtree
修改:
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>
关于为什么有 两个 childList
突变的问题,是的,我认为你是对的:他们正在移除 child,然后添加一个新的。如果我们使用 replaceChild
method,我们只会看到一个突变:
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>