2016-02-09 8 views
8

この質問は、thisという続編です。しかし、前のページを読む必要はありません。興味のある読者にリンクを張っています。 @Shomzが提案されているようMutationObserverを再接続して切断する

は、いくつかのクラスにすべての要素に反応するオブザーバー、あります:

var target = document.querySelectorAll(".someclass"); 
for (var i = 0; i < target.length; i++) { 
    create(target[i]); 
} 

function create(t) { 
    var observer = new MutationObserver(function(mutations) { 
     mutations.forEach(function(mutation) { 
      var foo = t.getAttribute("aaa") 
      if (foo == "vvv") 
       t.style.backgroundColor = "red"; 
     }); 
    }); 

    var config = { 
     attributes: true 
    }; 

    observer.observe(t, config); 
} 

ので、2つの密接に絡み合っての質問があります。

1)何らかの理由により、オブザーバが切断されている可能性があります。どのように私はそれを再接続することができますか? observer.observeを使用しようとしましたが、ここでは機能しません。

2)2番目の質問は、手動でオブザーバーを切断する方法は何ですか? observer.disconnect();を使用しようとしましたが、動作しません。

答えて

2

1)、観察者は、切断されてもよいです。どのように私はそれを再接続することができますか? observer.observeを使用しようとしましたが、ここでは機能しません。

2)2番目の質問は、手動でオブザーバーを切断する方法は何ですか? observer.disconnect();を使用しようとしましたが、動作しません。

あなたは正しい軌道に乗っていますが、事は、あなたが(undefinedを返します)が存在しないので、その範囲の外を意味する、それが中に定義されています機能のobserver変数外を使用しようとしているあります。

オリジナルのコードの更新例を参照してください。私はオブザーバを配列に移動し、その関数の外部でアクセスできるようにしたので、通常は切断して再接続できます。

問題は、ターゲット要素への参照を保持しているのと同じように、オブザーバーへの参照を保持しているだけでした。

var msg = document.getElementById('msg'); 
 
var target = document.querySelectorAll(".someClass"); 
 
// an array of observers 
 
var observers = []; 
 
// configuration of the observer 
 
var config = { attributes: true }; 
 

 
for (var i = 0; i < target.length; i++) { 
 

 
    // create an observer instance 
 
    observers[i] = new MutationObserver(function(mutations) { 
 
     mutations.forEach(function(mutation) { 
 
      var foo = mutation.target.getAttribute("bgColor") 
 

 
      if (foo) 
 
       mutation.target.style.backgroundColor = foo; 
 
     }); 
 
    }); 
 

 
    // pass in the target node, as well as the observer options 
 
    observers[i].observe(target[i], config); 
 
} 
 

 
msg.textContent = 'Starting timeouts'; 
 
// let's change an attribute in a second 
 
setTimeout(function(){ 
 
    target[2].setAttribute('bgColor', 'red'); 
 
    msg.textContent = 'Mutation observer should change the box to red'; 
 
}, 2000); 
 

 
setTimeout(function(){ 
 
    target[2].setAttribute('bgColor', 'green'); 
 
    msg.textContent = 'Mutation observer should change the box to green'; 
 
}, 4000); 
 

 
setTimeout(function(){ 
 
    observers[2].disconnect(); 
 
    msg.textContent = 'Mutation observer disconnected'; 
 
}, 6000); 
 

 
setTimeout(function(){ 
 
    target[2].setAttribute('bgColor', 'blue'); 
 
    msg.textContent = 'Mutation observer tries to change the box to blue, but is disconnected'; 
 
}, 8000); 
 

 
setTimeout(function(){ 
 
    target[1].setAttribute('bgColor', 'blue'); 
 
    msg.textContent = 'Let\'s try another box, which is not disconnected, all good'; 
 
}, 10000); 
 

 
setTimeout(function(){ 
 
    observers[2].observe(target[2], config); 
 
    msg.textContent = 'Mutation observer reconnected'; 
 
}, 12000); 
 

 
setTimeout(function(){ 
 
    target[2].setAttribute('bgColor', 'red'); 
 
    msg.textContent = 'Finally, the reconnected mutation observer should change the box to red'; 
 
}, 14000); 
 

 
setTimeout(function(){ 
 
    target[1].setAttribute('bgColor', 'white'); 
 
    target[2].setAttribute('bgColor', 'white'); 
 
    msg.textContent = 'Now try the manual controls below'; 
 
    document.getElementById('ctrl').style.display = 'block'; 
 
}, 16000);
.someClass { 
 
    width: 50px; 
 
    height: 50px; 
 
    display: inline-block; 
 
    border: 1px solid black 
 
} 
 

 
#ctrl {display: none}
<div class="someClass"></div> 
 
<div class="someClass"></div> 
 
<div class="someClass"></div> 
 
<div class="someClass"></div> 
 
<p id="msg"></p> 
 
<hr> 
 
<div id="ctrl"> 
 
<p>Change attribute: 
 
<button onclick="target[2].setAttribute('bgColor', 'red');">Red</button> 
 
<button onclick="target[2].setAttribute('bgColor', 'green');">Green</button> 
 
<button onclick="target[2].setAttribute('bgColor', 'blue');">Blue</button> 
 
</p><p>Manage the observer 
 
<button onclick="observers[2].disconnect();">Disconnect</button> 
 
<button onclick="observers[2].observe(target[2], config);">Reconnect</button> 
 
</p> 
 
</div>


UPDATE

要求されたとして、上記のアプローチは、他の(リンク)問題の私の最初の例の内側に置きます。基本的には、オブザーバを作成するための外部化された関数です。

var msg = document.getElementById('msg'); 
 
var target = document.querySelectorAll(".c"); 
 
// an array of observers 
 
var observers = []; 
 
// configuration of the observer 
 
var config = { attributes: true }; 
 

 
for (var i = 0; i < target.length; i++) { 
 
    create(target[i], i); 
 
} 
 

 
function create(t, i) { 
 
    // create an observer instance 
 
    observers[i] = new MutationObserver(function(mutations) { 
 
    mutations.forEach(function(mutation) { 
 
     var foo = t.getAttribute("bgColor") 
 

 
     if (foo) 
 
     t.style.backgroundColor = foo; 
 
    }); 
 
    }); 
 

 
    // pass in the target node, as well as the observer options 
 
    observers[i].observe(t, config); 
 
} 
 

 
// let's change an attribute in a second 
 
msg.textContent = 'Starting timeouts'; 
 
// let's change an attribute in a second 
 
setTimeout(function(){ 
 
    target[2].setAttribute('bgColor', 'red'); 
 
    msg.textContent = 'Mutation observer should change the box to red'; 
 
}, 2000); 
 

 
setTimeout(function(){ 
 
    target[2].setAttribute('bgColor', 'green'); 
 
    msg.textContent = 'Mutation observer should change the box to green'; 
 
}, 4000); 
 

 
setTimeout(function(){ 
 
    observers[2].disconnect(); 
 
    msg.textContent = 'Mutation observer disconnected'; 
 
}, 6000); 
 

 
setTimeout(function(){ 
 
    target[2].setAttribute('bgColor', 'blue'); 
 
    msg.textContent = 'Mutation observer tries to change the box to blue, but is disconnected'; 
 
}, 8000); 
 

 
setTimeout(function(){ 
 
    target[1].setAttribute('bgColor', 'blue'); 
 
    msg.textContent = 'Let\'s try another box, which is not disconnected, all good'; 
 
}, 10000); 
 

 
setTimeout(function(){ 
 
    observers[2].observe(target[2], config); 
 
    msg.textContent = 'Mutation observer reconnected'; 
 
}, 12000); 
 

 
setTimeout(function(){ 
 
    target[2].setAttribute('bgColor', 'red'); 
 
    msg.textContent = 'Finally, the reconnected mutation observer should change the box to red'; 
 
}, 14000); 
 

 
setTimeout(function(){ 
 
    target[1].setAttribute('bgColor', 'white'); 
 
    target[2].setAttribute('bgColor', 'white'); 
 
    msg.textContent = 'Now try the manual controls below'; 
 
    document.getElementById('ctrl').style.display = 'block'; 
 
}, 16000);
.c { 
 
    width: 50px; 
 
    height: 50px; 
 
    display: inline-block; 
 
    border: 1px solid black 
 
} 
 
#ctrl {display: none}
<div class="c"></div> 
 
<div class="c"></div> 
 
<div class="c"></div> 
 
<div class="c"></div> 
 
<p id="msg"></p> 
 
<hr> 
 
<div id="ctrl"> 
 
<p>Change attribute: 
 
<button onclick="target[2].setAttribute('bgColor', 'red');">Red</button> 
 
<button onclick="target[2].setAttribute('bgColor', 'green');">Green</button> 
 
<button onclick="target[2].setAttribute('bgColor', 'blue');">Blue</button> 
 
</p><p>Manage the observer 
 
<button onclick="observers[2].disconnect();">Disconnect</button> 
 
<button onclick="observers[2].observe(target[2], config);">Reconnect</button> 
 
</p> 
 
</div>

4

実際に複数のインスタンスを使用して複数のDOMノード要素を観察する必要はありません。
1つの変異観察者を使用して、複数のDOMノード要素を観察できます。
接続が切断された後にオブザーバを再接続するには、突然変異オブザーバの新しいインスタンスを再作成する必要はありません。すでに作成したインスタンスに対してobserveメソッドを再度呼び出すことができます。

disconnect()

DOM変異の通知を受けてからMutationObserverインスタンスを停止します。 observe()メソッドが再度使用されるまで、オブザーバのコールバックは呼び出されません。

既に観察されている要素に対してobserve()メソッドを呼び出すことは、観察に影響を与えません。少なくとも、観測に同じ観測者インスタンスを使用している場合。

注:要素にオブザーバーを追加することは、要素を複数回見ても差異がない場合は、addEventListenerと同じです。意味は、要素を2回観測すると、observeコールバックは2回起動せず、disconnect()を2回実行する必要もありません。言い換えれば、ある要素が観察されると、同じ観察者のインスタンスで再びそれを観察することは何もしません。しかし、コールバックオブジェクトが異なる場合、それはもちろん別のオブザーバを追加します。

ここでは、1つのオブザーバインスタンスを使用して、いくつかのイメージ要素の幅属性を観察する例を示します。この例では、タイムアウトを使用して各画像幅属性にランダム値を設定しています。コールバック関数は変更を出力し、オブザーバを切断して、プロセス全体を再び開始します。何らかの理由

var imgs = Array.prototype.slice.call(document.images), 
 
    config = { attributes: true, attributeOldValue: true }, 
 
    observer = new MutationObserver(mutationCallback); 
 

 
function mutationCallback (mutations) { 
 
    mutations.forEach(function(record) { 
 
    record.target.previousElementSibling.textContent = ""; 
 
    record.target.previousElementSibling.textContent = "The image " 
 
     + record.attributeName 
 
     + " attribute changed from " 
 
     + record.oldValue 
 
     + " to " 
 
     + record.target.getAttribute('width') 
 
     + "."; 
 
    }) 
 
    observer.disconnect(); 
 
    startObserving(imgs); 
 
} 
 

 
function changeNodeAttr (attr, nodes) { 
 
    window.setTimeout(function() { 
 
    nodes.forEach(function(node) { 
 
     node.setAttribute(attr, Math.floor(Math.random()*(300 - 100 + 1) +100)); 
 
    }) 
 
    }, 2500) 
 
} 
 

 
function startObserving (nodes) { 
 
    nodes.forEach(function(node) { 
 
    observer.observe(node, config); 
 
    }) 
 
    changeNodeAttr("width", imgs); 
 
} 
 

 
startObserving(imgs);
body { 
 
    font-family: sans-serif; 
 
} 
 

 
img { 
 
    display: block; 
 
    margin-bottom: 10px; 
 
}
<span></span> 
 
<img class="my-images" src="http://placehold.it/300x100?text=image" width="300"> 
 
<span></span> 
 
<img class="my-images" src="http://placehold.it/300x200?text=image" width="300"> 
 
<span></span> 
 
<img class="my-images" src="http://placehold.it/300x300?text=image" width="300">

関連する問題