ミューテーションオブザーバー API

概要

Mutation Observer API は、DOM の変更を監視するために使用されます。ノードの追加または削除、属性の変更、テキスト コンテンツの変更など、DOM 内の変更はすべて、この API によって通知できます。

概念的には、DOM が変更されると Mutation Observer イベントがトリガーされることが理解できます。ただし、イベントとは根本的に異なります。イベントは同期的にトリガーされます。つまり、DOM の変更は対応するイベントを即座にトリガーしますが、Mutation Observer は非同期でトリガーされ、DOM の変更はすぐにはトリガーされませんが、変更が行われるまで待機します。 current すべての DOM 操作が完了した後にトリガーされます。

この設計は、DOM の頻繁な変更に対応するためのものです。たとえば、1000 個の <p> 要素がドキュメントに連続して挿入されると、1000 個の挿入イベントが連続してトリガーされ、各イベントのコールバック関数が実行され、ブラウザが完全にフリーズする可能性があります。異なる場合は、1000 段落すべてが挿入された後にのみトリガーされ、一度だけトリガーされます。

Mutation Observer には以下の特徴があります。

  • すべてのスクリプト タスクが完了するまで待ってから実行します (つまり、非同期トリガー モード)。
  • DOM 変更を 1 つずつ処理するのではなく、DOM 変更レコードを処理用の配列にカプセル化します。
  • DOM 内のすべての種類の変更を監視することも、特定の種類の変更のみを監視するように指定することもできます。

MutationObserver コンストラクター

使用する場合は、まず MutationObserver コンストラクターを使用して新しいオブザーバー インスタンスを作成し、このインスタンスのコールバック関数を指定します。

varobserver = new MutationObserver(callback);

上記のコードのコールバック関数は、DOM が変更されるたびに呼び出されます。コールバック関数は 2 つのパラメーターを受け入れます。1 つ目は変更配列、2 つ目はオブザーバー インスタンスです。次に例を示します。

var observer = new MutationObserver(function (mutations, observer) {
  mutations.forEach(function(mutation) {
    console.log(突然変異);
  });
});

MutationObserver のインスタンス メソッド

観察する()

observe() メソッドは監視を開始するために使用されます。このメソッドは 2 つのパラメータを受け取ります。

  • 最初のパラメータ: 監視する DOM ノード
  • 2 番目のパラメータ: 監視する特定の変更を指定する構成オブジェクト
var 記事 = document.querySelector('記事');

var オプション = {
  'childList': true'属性':true
} ;

観察者.観察(記事、オプション);

上記のコードでは、observe() メソッドは 2 つのパラメータを受け入れます。1 つ目は、監視対象の DOM 要素が article であり、2 つ目は、監視対象の変更のタイプ (子ノードの変更と属性の変更) です。 。

オブザーバーが観察できる DOM 変更のタイプ (つまり、上記のコードの options オブジェクト) は次のとおりです。

  • childList: 子ノードの変更 (追加、削除、または変更を指します)。
  • 属性: 属性の変更。
  • characterData: ノードのコンテンツまたはノードのテキストの変更。

どのタイプの変更を観察するかを決定するには、「option」オブジェクトでその値を「true」として指定します。これら 3 つの観測値のうち少なくとも 1 つを同時に指定する必要があることに注意してください。何も指定されていない場合は、エラーが報告されます。

変更タイプに加えて、options オブジェクトは次のプロパティも設定できます。

  • subtree: このオブザーバーをこのノードのすべての子孫ノードに適用するかどうかを示すブール値。
  • attributeOldValue: attributes の変更を観察するときに、変更前の属性値を記録する必要があるかどうかを示すブール値。
  • characterDataOldValue: characterData の変更を観察するときに変更前の値を記録する必要があるかどうかを示すブール値。
  • attributeFilter: 観察する必要がある特定の属性を示す配列 (['class','src'] など)。
// ドキュメント ルート ノード (つまり、<html> タグ) の変更の監視を開始します。
mutationObserver.observe(document.documentElement, {
  属性: true、
  文字データ: truechildList: true、
  サブツリー: true、
  属性古い値: true、
  文字データ古い値: true
});

ノードへのオブザーバーの追加は、addEventListener() メソッドを使用するのと同じであり、同じオブザーバーを複数回追加することは無効であり、コールバック関数は 1 回だけトリガーされます。異なる options オブジェクトが指定されている場合は、上書きと同様に、後で追加されたオブジェクトが優先されます。

次の例では、新しく追加された子ノードを観察します。

var generatedNodes = [];
varobserver = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    for (var i = 0; i < mutation.addedNodes.length; i++) {
      insertNodes.push(mutation.addedNodes[i]);
    }
  });
  console.log(insertedNodes);
});
observer.observe(document, { childList: true, subtree: true });

切断()、takeRecords()

disconnect() メソッドは監視を停止するために使用されます。このメソッドを呼び出した後、DOM が再び変更された場合、オブザーバーはトリガーされません。

オブザーバー.切断();

takeRecords() メソッドは変更レコードをクリアするために使用されます。つまり、未処理の変更は処理されなくなります。このメソッドは、変更レコードの配列を返します。

オブザーバー.takeRecords();

以下に例を示します。

//オブザーバーによって処理されなかった変更をすべて保存します
var 変更 = mutationObserver.takeRecords();

// 観察をやめる
mutationObserver.disconnect();

MutationRecord オブジェクト

DOM が変更されるたびに、変更レコード (MutationRecord インスタンス) が生成されます。このインスタンスには、変更に関連するすべての情報が含まれています。 Mutation Observer は、「MutationRecord」インスタンスの配列を処理します。

MutationRecord オブジェクトには DOM 関連の情報が含まれており、次のプロパティがあります。

  • type: 観察された変更のタイプ (attributescharacterData、または childList)。
  • target: 変更された DOM ノード。
  • addedNodes: 新しく追加された DOM ノード。
  • removedNodes: 削除された DOM ノード。
  • previousSibling: 前の兄弟ノード。存在しない場合は、null を返します。
  • nextSibling: 次の兄弟ノードが存在しない場合、null を返します。
  • attributeName: 変更された属性。 attributeFilter が設定されている場合、事前に指定された属性のみが返されます。
  • oldValue: 変更前の値。この属性は、attribute および characterData の変更に対してのみ有効です。 childList が変更されると、null が返されます。

応用例

子要素の変更

次の例は、変更レコードを読み取る方法を示しています。

var callback = 関数 (レコード){
  records.map(関数(レコード){
    console.log('変異タイプ: ' + Record.type);
    console.log('ミューテーションターゲット: ' + Record.target);
  });
};

var mo = 新しい MutationObserver(コールバック);

var オプション = {
  'childList': true'サブツリー': true
};

mo.observe(document.body, オプション);

上記のコードのオブザーバーは、<body> のすべての下位ノードの変更を観察します (childList は子ノードを観察することを意味し、subtree は子孫ノードを観察することを意味します)。コールバック関数は、変更されたすべてのタイプとターゲット ノードをコンソールに表示します。

属性の変更

次の例は、プロパティの変更を追跡する方法を示しています。

var callback = 関数 (レコード) {
  records.map(関数 (レコード) {
    console.log('前の属性値: ' + Record.oldValue);
  });
};

var mo = 新しい MutationObserver(コールバック);

var 要素 = document.getElementById('#my_element');

var オプション = {
  「属性」: true'attributeOldValue': true
}

mo.observe(要素, オプション);

上記のコードは、最初に追跡属性の変更 ('attributes': true) を設定し、次に変更を記録する前に値を設定します。実際に変更が発生すると、コンソールには変更前の値が表示されます。

DOMContentLoaded イベントを置き換えます

Web ページがロードされると、DOM ノードの生成によって変更レコードが生成されるため、DOM 内の変更を観察している限り、関連するイベントを最初にトリガーできるため、DOMContentLoaded イベントを使用する必要はありません。 。

varobserver = new MutationObserver(callback);
オブザーバー.observe(document.documentElement, {
  childList: true、
  サブツリー: true
});

上記のコードでは、document.documentElement の子ノード (つまり、Web ページの <html>HTML ノード) の変更が監視されます。subtree 属性は、監視に子孫ノードも含まれることを指定します。したがって、Web ページ要素が生成されると、すぐに監視できます。

次のコードは、MutationObserver オブジェクトを使用して、DOM 生成を監視する関数をカプセル化します。

(関数(勝利){
  '厳密を使用';

  var リスナー = [];
  var doc = win.document;
  var MutationObserver = win.MutationObserver || win.WebKitMutationObserver;
  var オブザーバー。

  関数準備完了(セレクター、fn){
    //ストレージセレクターとコールバック関数
    リスナー.push({
      セレクター: セレクター、
      ふん:ふん
    });
    if(!オブザーバー){
      // ドキュメントの変更を監視する
      オブザーバー = 新しい MutationObserver(check);
      observer.observe(doc.documentElement, {
        childList: true、
        サブツリー: true
      });
    }
    // ノードがすでに DOM 内にあるかどうかを確認します
    チェック();
  }

  関数チェック(){
  // 保存されているノードと一致するかどうかを確認します
    for(var i = 0; i < listens.length; i++){
      var リスナー = リスナー[i];
      // 指定されたノードに一致するノードがあるかどうかを確認します
      var 要素 = doc.querySelectorAll(listener.selector);
      for(var j = 0; j < elements.length; j++){
        var 要素 = 要素[j];
        // コールバック関数がこの要素に対して 1 回だけ呼び出されるようにします
        if(!element.ready){
          element.ready = true;
          // ノード上でコールバック関数を呼び出します。
          listener.fn.call(要素, 要素);
        }
      }
    }
  }

  // 外の世界に公開する準備ができました
  win.ready = 準備完了;

})(これ);

// 使い方
ready('.foo', function(element){
  // ...
});

参考リンク


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0