DocumentFragment
DocumentFragmentは通常のノードとは少し違い、複数のノードをまとめて持つことができます。
また、単独で存在し、使用することができます。
DocumentFragmentのノードは、parentNodeを持つことがなくnullになります。
子ノードを持つことができるので、そのノードは操作することができます。
DocumentFragmentを使った実例を使って、どんな動きをするのかを確認してみます。
まずは、DocumentFragmentを作成してみます。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テストHTML</title> </head> <body> <div id="p1" name="p1name"> <div id="c1" name="c1name">c1text</div> <div id="c2" name="c2name">c2text</div> <div id="c3" name="c3name">c3text</div> </div> <script type="text/javascript"> // DocumentFragmentを作成する let frag = document.createDocumentFragment(); console.log(frag); </script> </body> </html>
出力結果ですが、コンソールログには以下のように出力されます。
DocumentFragment [] baseURI: "https://propansystem.net/blogsample/js/040/test1.html" childElementCount: 0 childNodes: NodeList [] children: HTMLCollection { length: 0 } firstChild: null firstElementChild: null isConnected: false lastChild: null lastElementChild: null nextSibling: null nodeName: "#document-fragment" nodeType: 11 nodeValue: null ownerDocument: HTMLDocument https://propansystem.net/blogsample/js/040/test1.html parentElement: null parentNode: null previousSibling: null textContent: "" <prototype>: DocumentFragmentPrototype { getElementById: getElementById(), querySelector: querySelector(), querySelectorAll: querySelectorAll(), … }
これは内容が空のDocumentFragmentノードが生成されたことを表します。
また、DocumentFragmentノードを作成しただけでは、まだHTMLドキュメントには何も影響を及ぼさないです。
別な方法だと、オブジェクトのコンストラクタを使用してnewすることもできます。
let frag = new DocumentFragment();
上記のように書くと同じノード「frag」が生成されます。
DocumentFragmentを使ってノードを生成する
では次にDocumentFragmentを使ってHTMLドキュメントに対してノードを追加してみます。
先ほどのHTMLサンプルに次のコードを追記しました。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テストHTML</title> </head> <body> <div id="p1" name="p1name"> <div id="c1" name="c1name">c1text</div> <div id="c2" name="c2name">c2text</div> <div id="c3" name="c3name">c3text</div> </div> <script type="text/javascript"> // DocumentFragmentを作成する let frag = document.createDocumentFragment(); // 子ノードを作成する let c4 = document.createElement('c4'); let c5 = document.createElement('c5'); let c6 = document.createElement('c6'); frag.append(c4); frag.append(c5); frag.append(c6); console.log(frag); </script> </body> </html>
出力結果は以下のようになります。
DocumentFragment(3) [ c4, c5, c6 ] baseURI: "https://propansystem.net/blogsample/js/040/test2.html" childElementCount: 3 childNodes: NodeList(3) [ c4, c5, c6 ] children: HTMLCollection { 0: c4, 1: c5, length: 3, … } firstChild: <c4> firstElementChild: <c4> isConnected: false lastChild: <c6> lastElementChild: <c6> nextSibling: null nodeName: "#document-fragment" nodeType: 11 nodeValue: null ownerDocument: HTMLDocument https://propansystem.net/blogsample/js/040/test2.html parentElement: null parentNode: null previousSibling: null textContent: "" <prototype>: DocumentFragmentPrototype { getElementById: getElementById(), querySelector: querySelector(), querySelectorAll: querySelectorAll(), … }
ここでは、DocumentFragmentノードに対して、c4、c5、c6の子ノードが追加されたことがわかります。
では次にDocumentFragmentを他のノードに追加してみます。
先ほどの例のHTMLを使い、「p1」のノードに対して、fragを追加してみます。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テストHTML</title> </head> <body> <div id="p1" name="p1name"> <div id="c1" name="c1name">c1text</div> <div id="c2" name="c2name">c2text</div> <div id="c3" name="c3name">c3text</div> </div> <script type="text/javascript"> // DocumentFragmentを作成する let frag = document.createDocumentFragment(); // 子ノードを作成する let c4 = document.createElement('div'); let c5 = document.createElement('div'); let c6 = document.createElement('div'); // 作成した子ノードに、HTMLタグとテキストをセットする c4.appendChild(document.createTextNode('c4text')); c5.appendChild(document.createTextNode('c5text')); c6.appendChild(document.createTextNode('c6text')); frag.append(c4); frag.append(c5); frag.append(c6); console.log(frag); // Elementノードを取得 let p1 = document.getElementById("p1"); // p1のノードにDocumentFragmentを追加する p1.append(frag); </script> </body> </html>
出力結果についてですが、まず、console.logは以下のようになります。
DocumentFragment(3) [ div, div, div ] baseURI: "https://propansystem.net/blogsample/js/040/test3.html" childElementCount: 0 childNodes: NodeList [] children: HTMLCollection { length: 0 } firstChild: null firstElementChild: null isConnected: false lastChild: null lastElementChild: null nextSibling: null nodeName: "#document-fragment" nodeType: 11 nodeValue: null ownerDocument: HTMLDocument https://propansystem.net/blogsample/js/040/test3.html parentElement: null parentNode: null previousSibling: null textContent: "" <prototype>: DocumentFragmentPrototype { getElementById: getElementById(), querySelector: querySelector(), querySelectorAll: querySelectorAll(), … }
次に、画面上のHTMLソースは以下のようになります。(bodyタグ内だけの抜粋です)
<div id="p1" name="p1name"> <div id="c1" name="c1name">c1text</div> <div id="c2" name="c2name">c2text</div> <div id="c3" name="c3name">c3text</div> <div>c4text</div> <div>c5text</div> <div>c6text</div> </div>
どうゆう動作になったかというと、上の結果からもわかるとおり、
DocumentFragmentノードそのものは、元のp1の親ノードには影響を及ぼさず、もともとp1が持っていた
子ノードにも影響を及ぼさずに、DocumentFragmentにappendした子ノード「c4」「c5」「c6」だけがp1のノードに追加されています。
上記のような動きをするので、DocumentFragmentは一時的なDOMツリーを生成し、
そこに子ノードを追加してひとまとめにして、他の親ノードに対してまとめた子ノードを追加する。
といった場面で使えると言えます。