如果我使用 setAttribute,MutationObserver 会挂起

MutationObserver hangs if I use setAttribute

本文关键字:MutationObserver 挂起 setAttribute 如果      更新时间:2023-09-26

我有一个观察者,它会监听listitemdiv属性的任何变化,如果属性发生变化,它会将该div的背景颜色设置为红色。

实际上,您可以自己轻松测试它。打开Chrome的书签管理器,在控制台中启动此脚本,然后单击任何书签或文件夹。它将被涂成红色。

问题在代码块的中间提到:如果我使用 setAttribute,脚本将被挂起。

第一种方法(使用 style.attributeName )不适合我,因为在我的实际代码中,我使用自定义属性,而不是 background-color

这个问题看起来很奇怪。它可以通过什么方式解决?

<div role="listitem"></div>
<div role="listitem"></div>
<div role="listitem"></div>
<script>
var target = document.querySelectorAll("[role='listitem']");
for (var i = 0; i < target.length; i++) {
    // create an observer instance
    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {

            // The Problem
            // ===========
            // This work well
            mutation.target.style.backgroundColor = "red";
            // But this doesn't
            // mutation.target.setAttribute("style", "background-color: red;");
        });
    });
    // configuration of the observer
    var config = { attributes: true };
    // pass in the target node, as well as the observer options
    observer.observe(target[i], config);
}
</script>

您通过更改属性来响应每个属性更改。这会导致问题也就不足为奇了:你会让观察者再次开火。显然,即使您设置了相同的值,setAttribute也会更新属性对象(我认为这并非不合理,尽管有点令人惊讶)。

相反,我只会在它确实需要更改时才设置它:

if (mutation.target.getAttribute("yourattr") != targetvalue) {
    mutation.target.setAttribute("yourattr", targetvalue);
}

我已经检查过将属性设置为相同值是否会再次触发观察者(无论如何,在 Chrome 上):

var target = document.getElementById("target");
var counter = 0;
var observer = new MutationObserver(function() {
    ++counter;
    console.log(Date.now() + ": " + counter);
    if (counter < 10) {
        console.log("Inside handler: Setting data-foo to bar");
        target.setAttribute("data-foo", "bar");
    } else {
        console.log("Inside handler: Stopped, to avoid looping forever");
    }
});
observer.observe(target, {attributes: true});
console.log("Initial change: Setting data-something-else to testing");
target.setAttribute("data-something-else", "testing");
<div id="target"></div>

因此,首先检查可以防止这种情况发生:

var target = document.getElementById("target");
var observer = new MutationObserver(function() {
    console.log(Date.now() + ": In handler");
    if (target.getAttribute("data-foo") != "bar") {
        console.log("Inside handler: Setting data-foo to bar");
        target.setAttribute("data-foo", "bar");
    } else {
        console.log("Inside handler: No need to set it, it's already set");
    }
});
observer.observe(target, {attributes: true});
console.log("Initial change: Setting data-something-else to testing");
target.setAttribute("data-something-else", "testing");
<div id="target"></div>

相关文章:
  • 没有找到相关文章