如果我使用setAttribute,MutationObserver会挂起

时间:2016-02-02 12:33:23

标签: javascript mutation-observers

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

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

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

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

问题看起来很奇怪。它可以解决的方式是什么?

background-color

1 个答案:

答案 0 :(得分:2)

您通过更改属性来响应每个属性更改。毫无疑问,这会导致一个问题:你会让观察者再次开火。显然,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;
  snippet.log(Date.now() + ": " + counter);
  if (counter < 10) {
    snippet.log("Inside handler: Setting data-foo to bar");
    target.setAttribute("data-foo", "bar");
  } else {
    snippet.log("Inside handler: Stopped, to avoid looping forever");
  }
});
observer.observe(target, {attributes: true});
snippet.log("Initial change: Setting data-something-else to testing");
target.setAttribute("data-something-else", "testing");
&#13;
<div id="target"></div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
&#13;
&#13;

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

&#13;
&#13;
var target = document.getElementById("target");
var observer = new MutationObserver(function() {
  snippet.log(Date.now() + ": In handler");
  if (target.getAttribute("data-foo") != "bar") {
    snippet.log("Inside handler: Setting data-foo to bar");
    target.setAttribute("data-foo", "bar");
  } else {
    snippet.log("Inside handler: No need to set it, it's already set");
  }
});
observer.observe(target, {attributes: true});
snippet.log("Initial change: Setting data-something-else to testing");
target.setAttribute("data-something-else", "testing");
&#13;
<div id="target"></div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
&#13;
&#13;