【问题标题】:MutationObserver hangs if I use setAttribute如果我使用 setAttribute,MutationObserver 会挂起
【发布时间】:2016-02-02 12:33:23
【问题描述】:

我有一个观察者,它会监听listitem divs 属性的任何变化,如果attibutes 发生变化,它会将那个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>

【问题讨论】:

    标签: javascript mutation-observers


    【解决方案1】:

    您通过更改属性来响应每个属性更改。这会导致一个问题也就不足为奇了:你会让观察者再次开火。显然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");
    &lt;div id="target"&gt;&lt;/div&gt;

    所以首先检查可以防止这种情况发生:

    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");
    &lt;div id="target"&gt;&lt;/div&gt;

    【讨论】:

      猜你喜欢
      • 2019-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多