如何在 MutationObserver 的回调中“暂停”观察

Posted

技术标签:

【中文标题】如何在 MutationObserver 的回调中“暂停”观察【英文标题】:How to "Pause" observing in callback of a MutationObserver 【发布时间】:2017-11-14 03:36:30 【问题描述】:

比如我想在.my-codes写一些代码。

<head>
<script class="my-codes">
    var ob = new MutationObserver(
        function (mutations) 
            mutations.forEach(
                mutation => 
                    mutation.addedNodes.forEach(
                        node => 
                            if(node.nodeName === "DIV")
                                // Without this browser may crush for infinite recursion
                                this.disconnect(); 
                                let innerNode = document.createElement("div");
                                innerNode.className = "inner-div";
                                console.log("Insert div to a ." + node.className);
                                node.appendChild(innerNode);
                                // Method below does not exist
                                /* this.reconnect(); */ 
                            
                        
                    )
                
            );
        
    );
    ob.observe(document, childList:true, subtree:true);
</script>
</head>
<body>
    <div class="div1">
        <script>
            let asyncDiv = document.createElement("div");
            asyncDiv.className = "div3";
            setTimeout(()=>document.body.appendChild(asyncDiv), 10);
        </script>
    </div>
    <div class="div2"></div>
</body>

预期结果(如果存在 this.reconnect(); 之类的东西):

<div class="div1">
    <div class="inner-div"></div>
</div>
<div class="div2">
    <div class="inner-div"></div>
</div>
<div class="div3">
    <div class="inner-div"></div>
</div>

实际结果(第一次插入后观察完全停止):

<div class="div1">
    <div class="inner-div"></div>
</div>
<div class="div2"></div>
<div class="div3"></div>

有没有可靠的方法来实现this.reconnect();函数?

(最好不要乱用全局变量,下面的代码不认为是可靠的方法,因为回调函数需要捕获全局变量)

var target = document;
var config = childList:true, subtree:true;
var ob = new MutationObserver(
    function(mut, observer)
        this.disconnect();
        /* mess with DOM */
        observer.observe(target, config);
    
)
ob.observe(target, config);

【问题讨论】:

【参考方案1】:

这似乎是使用某种全局变量的正确方法。但它们不需要是全球性的:

function observe(target,config)
  target =target|| document;
  config = config||childList:true, subtree:true;
  var ob = new MutationObserver(function(mut, observer)
      ob.disconnect();
    /* mess with DOM */
      ob.observe(target, config);
  );
 ob.observe(target, config);


observe();

这可以扩展以提供更通用的观察方式:

function customObserver(target,config,callback)
 this.target =target|| document;
 this.config = config||childList:true, subtree:true;
 var that=this;
 this.ob = new MutationObserver(function(mut,observer)
    callback.call(that,mut,observer);
 );
 

customObserver.prototype=
  connect:function()
    this.ob.observe(this.target,this.config);
  ,
 disconnect:function() this.ob.disconnect()
;

所以可以这样做:

var observer=new customObserver(document,false,function(observer,mutations)
  observer.disconnect();
  //som DOM changes
 observer.connect();
);
observer.connect();

【讨论】:

事实上我是尝试reconnect的人,我正在使用来自https://greasyfork.org/scripts/12228/code/setMutationHandler.jssetMutationHandler。我没有找到访问原始目标和配置的方法。不修改原来的setMutationHandler.js可以reconnect吗?

以上是关于如何在 MutationObserver 的回调中“暂停”观察的主要内容,如果未能解决你的问题,请参考以下文章

30天精通JavaScript第24天 DOM规范中的MutationObserver接口

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

DOM规范

断开 Mutation Observer 与回调函数的连接

如何在多个节点上使用 MutationObserver?

JavaScript是如何工作的:使用MutationObserver跟踪DOM的变化