单个 MutationObserver 对象可以观察多个目标吗?

Posted

技术标签:

【中文标题】单个 MutationObserver 对象可以观察多个目标吗?【英文标题】:Can a single MutationObserver object observe multiple targets? 【发布时间】:2015-08-28 17:53:42 【问题描述】:

我想使用 MutationObserver 对象来观察我的一些 DOM 节点的变化。

文档给出了创建MutationObserver 对象并将其注册到目标的示例。

// select the target node
var target = document.querySelector('#some-id');

// create an observer instance
var observer = new MutationObserver(function(mutations) 
  mutations.forEach(function(mutation) 
    console.log(mutation.type);
  );    
);

// configuration of the observer:
var config =  attributes: true, childList: true, characterData: true ;

// pass in the target node, as well as the observer options
observer.observe(target, config);

假设我有上面的代码,但就在它下面,我放置了这个代码:

var target2 = document.querySelector('#some-other-id');
var config2 = attributes: true, subtree: true;
observer.observe(target2, config2);

observer

现在正在观察 2 个目标? 它会停止观察target吗? 会决定不关注target2吗? 会报错吗? 还是会表现出其他一些行为?

【问题讨论】:

是否可以通过MutationObserver 观察 的变化?? 【参考方案1】:

观察者现在将根据您的定义观察两个目标 - targettarget2。不会抛出任何错误,并且target 不会被“取消注册”以支持target2。不会出现意外或其他行为。

这是一个在两个 contenteditable 元素上使用相同 MutationObserver 的示例。要查看此内容,请从每个 contenteditable 元素中删除 <span> 节点,然后查看两个观察到的元素的行为范围。

<div id="myTextArea" contenteditable="true">
    <span contenteditable="false">Span A</span>
</div>

<div id="myTextArea2" contenteditable="true">
    <span contenteditable="false">Span B</span>
</div>

var observer = new MutationObserver(function(mutations) 
  mutations.forEach(function(mutation) 
      //console.log($(mutation.removedNodes)); // <<-- includes text nodes

      $(mutation.removedNodes).each(function(value, index) 
          if(this.nodeType === 1) 
              console.log(this)
          
      );
  );
);

var config =  attributes: true, childList: true, characterData: true ;

observer.observe($('#myTextArea')[0], config);

observer.observe($('#myTextArea2')[0], config);

JSFiddle Link - 演示

请注意,我为第一个演示回收了相同的配置,但是,放置一个新配置将是该观察到的元素所独有的。以config2 中定义的示例为例,如果在#myTextArea2 上使用,您将看不到根据配置选项记录的节点,但请注意#myTextArea 的观察者不受影响。

JSFiddle Link - 演示 - 配置排他性

【讨论】:

非常好!虽然我想知道这是否在所有浏览器中都一致,我想知道如果你碰巧在你开始观察的元素中观察到一个元素,它是否是一致的? 另外需要注意的是,多次观察同一个目标,不会导致多次调用回调来更改该元素。 这里有一个问题:我们如何unobserve我们正在观察的元素之一?似乎disconnect() 方法会使 MutationObserver 停止观察所有元素!这意味着每个元素都没有清理,这意味着内存泄漏的可能性! 好吧,我猜你必须断开连接,然后重新观察你需要的元素。我几乎更愿意向它传递一个实时 htmlCollection 并让它自动监视所有这些元素,即使添加和删除节点也是如此。 @theonlygusti 似乎只有两个选项:每个元素使用一个 MO,或者在单个 MO 上调用断开连接,然后再次观察除您不再希望观察的元素之外的所有元素。还有一个关于为其添加 API 的规范讨论:github.com/WICG/webcomponents/issues/940

以上是关于单个 MutationObserver 对象可以观察多个目标吗?的主要内容,如果未能解决你的问题,请参考以下文章

可以用来监听Dom类名样式变化的方法: MutationObserver

MutationObserver 点击元素/类

MutationObserver 无法观察 textarea

MutationObserver监听DOM变化

JQuery如何监听一个DIV宽高的变化?

MutationObserver监听DOM元素结构变化和属性变化实例