如何测试MutationObserver

时间:2017-07-19 11:43:55

标签: javascript html mutation-observers

我想同步一些DOM节点属性。如果更改了某个属性,则会更改其他元素属性。

我可以改变它,但我不能为它编写测试。测试更改观察元素的属性,然后检查应用于其他元素的更改。更改同步最终会发生,但不会在观察到的元素属性更改后立即发生。

this example中,我创建了三个div,并希望将#div1的class属性与其他两个同步。

HTML:

<div id="div1" class="foo"></div>
<div id="div2" class="foo"></div>
<div id="div3" class="foo"></div>

JS:

let div1 = document.getElementById("div1")
let div2 = document.getElementById("div2")
let div3 = document.getElementById("div3")

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.target.getAttribute("class"))
    //sync the new attribute value to
    div2.setAttribute("class", mutation.target.getAttribute("class"))
    div3.setAttribute("class", mutation.target.getAttribute("class"))
  })
})
// pass in the target node, as well as the observer options
observer.observe(div1, { attributes: true, attributeFilter: ["class"]})

//the test sets the class attribute of div1 to 'bar'
div1.setAttribute("class", "bar")
//then checks if div2 and div3 class is set to 'bar'
console.log("is div2.class = 'bar'?", div2.getAttribute("class") == "bar")
console.log("is div3.class = 'bar'?", div3.getAttribute("class") == "bar")

输出是:

is div2.class = 'bar'? false
is div3.class = 'bar'? false
bar

MutationObserver仅在检查后运行,然后div2.classdiv3.class设置为'bar'。所以我的问题是,如何使用MutationObserver测试属性的同步。

1 个答案:

答案 0 :(得分:2)

在检查更新的类之前,您需要等待变异观察者处理变异事件。

常见的诀窍是使用setTimeout。有关其工作原理,请参阅this question

&#13;
&#13;
let div1 = document.getElementById("div1");
let div2 = document.getElementById("div2");
let div3 = document.getElementById("div3");

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.target.getAttribute("class"));
    div2.setAttribute("class", mutation.target.getAttribute("class"));
    div3.setAttribute("class", mutation.target.getAttribute("class"));
  });
});
// pass in the target node, as well as the observer options
observer.observe(div1, {
  attributes: true,
  attributeFilter: ["class"]
});

function testMutationObserver(mutation, afterMutation) {
  //Perform the mutation, e.g. by setting a new class
  mutation();
  
  //setTimeout gives the MutationObserver a chance to see the changes
  setTimeout(afterMutation);
}

testMutationObserver(
  function() {
    div1.setAttribute("class", "bar");
  },
  function() {
    console.log("is div2.class = 'bar'?", div2.getAttribute("class") == "bar");
    console.log("is div3.class = 'bar'?", div3.getAttribute("class") == "bar");
  }
);
&#13;
<div id="div1" class="foo"></div>
<div id="div2" class="foo"></div>
<div id="div3" class="foo"></div>
&#13;
&#13;
&#13;