Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

MutationObserver中subtree的坑

  MutationObserver的配置参数中可以将subtree置为true来让其拥有对子树监视的能力。但这个概念有点逗,主意是“子树”,不是“后代节点”。如果我们如果将子树先构建好后再将子树的树根插入被监视的树上就只会监视到一次插入,这个逻辑是正确的。
  subtree:true的意思是,被监视元素的所有后代节点也同样被监视,但监视的依然只是插入和移除的动作本身,无论是插入一个节点还是一颗子树,都仅视为一次插入。这里设计了三个测试,从结果大概可以看出概念来:
<script>
var mo=new MutationObserver(function(e){
  e.forEach(function(e){
    Array.prototype.forEach.call(e.addedNodes,function(e){
      console.log(e);
    });
  });
});
onload=function(){
  mo.observe(document.body,{childList:true,subtree:true});
  var div=document.createElement("div");

  // 测试1 先建好子树,一次性插入被监视的树中:监控到 1 次插入
  var outer1=div.cloneNode();
  var inner1=div.cloneNode();
  outer1.className="outer1";
  inner1.className="inner1";
  outer1.appendChild(inner1);
  document.body.appendChild(outer1);

  // 测试2 直接在被监视的树上建子树:监控到 2 次插入
  var outer2=div.cloneNode();
  var inner2=div.cloneNode();
  outer2.className="outer2";
  inner2.className="inner2";
  document.body.appendChild(outer2);
  outer2.appendChild(inner2);

  // 测试3 插入HTML文本:监控到 1 次插入
  document.body.insertAdjacentHTML(
    "beforeend",
    '<div class="outer3"><div class="inner3"></div></div>'
  );
};
</script>

  直接对文档插入HTML文本的话,HTML文本是会先被做一个文档片段后插入,所以上面的测试3中只会监视到一次插入。当然,也不是说它就一定值会监视到一次插入,对文档片段的插入得看有多少个子节点(注意是子节点不是后代节点),因为子节点是逐个插入的。上面的测试3中只有一个子节点,所以才只监视到一次插入,如果是这样的代码,就不止一次了:
<script>
var mo=new MutationObserver(function(e){
  e.forEach(function(e){
    Array.prototype.forEach.call(e.addedNodes,function(e){
      console.log(e);
    });
  });
});
onload=function(){
  mo.observe(document.body,{childList:true,subtree:true});
  var fragment=document.createDocumentFragment();
  fragment.appendChild(document.createElement("div"));
  fragment.appendChild(document.createElement("div"));
  document.body.appendChild(fragment);
};
</script>
  另外,如果我没记错的话,Firefox32之前的版本存在BUG,在一些情况下它直接在被监视对象上建立子树了,会造成多次触发。当时就想说这个问题,但眼看Firefox33就修复了,所以拖到现在才说。
网名:
3.84.186.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^