DOMをトラバースする方法

前書き

このシリーズの以前のチュートリアル、https://www.digitalocean.com/community/tutorials/how-to-access-elements-in-the-dom [DOMの要素にアクセスする方法]は、ビルドされた-ID、クラス、タグ名、クエリセレクターによってHTML要素にアクセスするための `+ document `オブジェクトのメソッド。 DOMは、ルートに「 document +」ノードを持つhttps://www.digitalocean.com/community/tutorials/understanding-the-dom-tree-and-nodes [ノードのツリー]として構成され、さまざまなブランチとしての他のすべてのノード(要素、コメント、テキストノードを含む)。

多くの場合、すべての要素を事前に指定せずにDOM内を移動する必要があります。 JavaScriptとHTMLの操作方法を理解するには、DOMツリーを上下に移動し、ブランチ間を移動する方法を学ぶことが不可欠です。

このチュートリアルでは、親、子、および兄弟のプロパティを使用してDOMをトラバースする方法(DOMのウォーキングまたはナビゲートとも呼ばれます)について説明します。

セットアップ

まず、次のコードで構成される「+ nodes.html +」という新しいファイルを作成します。

nodes.html

<!DOCTYPE html>
<html>

<head>
 <title>Learning About Nodes</title>

 <style>
   * { border: 2px solid #dedede; padding: 15px; margin: 15px; }
   html { margin: 0; padding: 0; }
   body { max-width: 600px; font-family: sans-serif; color: #333; }
 </style>
</head>

<body>
 <h1>Shark World</h1>
 <p>The world's leading source on <strong>shark</strong> related information.</p>
 <h2>Types of Sharks</h2>
 <ul>
   <li>Hammerhead</li>
   <li>Tiger</li>
   <li>Great White</li>
 </ul>
</body>

<script>
 const h1 = document.getElementsByTagName('h1')[0];
 const p = document.getElementsByTagName('p')[0];
 const ul = document.getElementsByTagName('ul')[0];
</script>

</html>

ファイルをWebブラウザーにロードすると、次のスクリーンショットのようなレンダリングが表示されます。

画像:https://assets.digitalocean.com/articles/eng_javascript/dom/nodes-before-modification.png [nodes.html page]

このWebサイトの例では、いくつかの要素を持つHTMLドキュメントがあります。 いくつかの基本的なCSSが `+ style `タグに追加されて、各要素がはっきり見えるようになり、いくつかの要素に簡単にアクセスできるように、いくつかの変数が ` script `に作成されました。 各「 h1 」、「 p 」、および「 ul 」はそれぞれ1つしかないため、それぞれの「 getElementsByTagName +」プロパティの最初のインデックスにアクセスできます。

ルートノード

+ document`オブジェクトはDOMのすべてのノードのルートです。 このオブジェクトは実際には `+ window`オブジェクトのプロパティであり、ブラウザのタブを表すグローバルな最上位オブジェクトです。 https://developer.mozilla.org/en-US/docs/Web/API/Window [+ window `]オブジェクトは、ツールバー、ウィンドウの高さと幅、プロンプト、アラートなどの情報にアクセスできます。 ` document`は、内部の` + window`の内側にあるもので構成されます。

以下は、すべてのドキュメントに含まれるルート要素で構成されるチャートです。 空白のHTMLファイルがブラウザーにロードされた場合でも、これらの3つのノードが追加され、DOMに解析されます。

Property Node Node Type

document

#document

DOCUMENT_NODE

document.documentElement

html

ELEMENT_NODE

document.head

head

ELEMENT_NODE

document.body

body

ELEMENT_NODE

+ html、` + head`、および `+ body `要素は非常に一般的であるため、 ` document`には独自のプロパティがあります。

DevToolsで_Console_を開き、これらの4つのプロパティを送信して出力を表示することにより、これらの4つのプロパティをそれぞれテストします。 また、 + h1 ++ p +、および `+ ul `をテストして、 ` script +`タグに追加した変数による要素を返すこともできます。

親ノード

DOMのノードは、他のノードとの関係に応じて、親、子、および兄弟と呼ばれます。 任意のノードの*親*は、その1つ上のレベル、またはDOM階層の + document +`に近いノードです。 親を取得する2つのプロパティ-+ parentNode `と ` parentElement +`があります。

Property Gets

parentNode

Parent Node

parentElement

Parent Element Node

`+ nodes.html +`の例では:

  • + html`は + head`、 + body、および` + script& `の親です。

  • 「+ body 」は「 h1 」、「 h2 」、「 p 」、「 ul 」の親ですが、「 li 」は「 body 」から2レベル下にあるため、「 li +」ではありません。

`+ p `要素の親が ` parentNode `プロパティでテストできます。 この ` p `変数は、カスタムの ` document.getElementsByTagName( 'p')[0] +`宣言から取得されます。

p.parentNode;
Output► <body>...</body>

`+ p `の親は ` body +`ですが、どうやって祖父母を取得できますか。これは上の2レベルです。 これは、プロパティを連鎖させることで実現できます。

p.parentNode.parentNode;
Output► <html>...</html>

`+ parentNode `を2回使用して、 ` p +`の祖父母を取得しました。

ノードの親を取得するためのプロパティがありますが、以下のスニペットで示すように、それらの間にわずかな違いが1つだけあります。

// Assign html object to html variable
const html = document.documentElement;

console.log(html.parentNode); // > #document
console.log(html.parentElement); // > null

テキストとコメントは他のノードの親になることはできないため、ほとんどすべてのノードの親は要素ノードです。 ただし、「+ html」の親はドキュメントノードであるため、「+ parentElement」は「+ null i」を返します。 一般に、DOMを走査するときは `+ parentNode +`がより一般的に使用されます。

子ノード

ノードの*子供*は、その1レベル下のノードです。 1レベルのネストを超えるノードは通常、子孫と呼ばれます。

Property Gets

childNodes

Child Nodes

firstChild

First Child Node

lastChild

Last Child Node

children

Element Child Nodes

firstElementChild

First Child Element Node

lastElementChild

Last Child Element Node

`+ childNodes `プロパティは、ノードのすべての子のライブリストを返します。 ` ul `要素が3つの ` li +`要素を取得することを期待するかもしれません。 取得するものをテストしましょう。

ul.childNodes;
Output► (7) [text, li, text, li, text, li, text]

3つの `+ li +`要素に加えて、4つのテキストノードも取得します。 これは、独自のHTML(JavaScriptによって生成されたものではない)を作成し、要素間のインデントがDOMでテキストノードとしてカウントされるためです。 DevToolsの[要素]タブは空白ノードを削除するため、これは直感的ではありません。

`+ firstChild +`プロパティを使用して最初の子ノードの背景色を変更しようとすると、最初のノードがテキストであるため失敗します。

ul.firstChild.style.background = 'yellow';
OutputUncaught TypeError: Cannot set property 'background' of undefined

これらのタイプの状況では、要素ノードのみを取得するために、 + children +、 `+ firstElementChild `および ` lastElementChild `プロパティが存在します。 ` ul.children `は3つの ` li +`要素のみを返します。

`+ firstElementChild `を使用して、 ` ul `の最初の ` li +`の背景色を変更できます。

ul.firstElementChild.style.background = 'yellow';

上記のコードを実行すると、Webページが更新されて背景色が変更されます。

画像:https://assets.digitalocean.com/articles/eng_javascript/dom/traverse-1.png [firstElementChild.style.background modification]

この例のように基本的なDOM操作を行う場合、要素固有のプロパティは非常に役立ちます。 JavaScriptで生成されたWebアプリでは、すべてのノードを選択するプロパティが使用される可能性が高くなります。この場合、空白の改行とインデントは存在しないためです。

https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-javascript#forof-loop [+ for …​ of +]ループを使用して、すべてを反復処理できます。 `+ children +`要素。

for (let element of ul.children) {
 element.style.background = 'yellow';
}

これで、各子要素の背景が黄色になります。

image:https://assets.digitalocean.com/articles/eng_javascript/dom/traverse-2.png [子要素の変更]

`+ p `要素にはテキストと要素の両方が含まれているため、 ` childNodes +`プロパティはその情報にアクセスするのに役立ちます。

for (let element of p.childNodes) {
 console.log(element);
}
Output"The world's leading source on "
<strong>​shark​</strong>​
" related information."

`+ childNodes `と ` children `は、すべてのhttps://www.digitalocean.com/community/tutorial_series/working-with-arrays-in-javascript[Array properties and methods]を持つ配列を返しませんが、表示され、 JavaScript配列と同様に動作します。 インデックス番号でノードにアクセスするか、 ` length`プロパティを見つけることができます。

document.body.children[3].lastElementChild.style.background = 'fuchsia';

上記のコードは、 + body +`の4番目の子要素( `+ ul +)の最後の要素の子( + li +)を見つけ、スタイルを適用します。

image:https://assets.digitalocean.com/articles/eng_javascript/dom/traverse-3.png [最後の子要素の変更]

親プロパティと子プロパティを使用して、DOM内の任意のノードを取得できます。

兄弟ノード

ノードの*兄弟*は、DOMの同じツリーレベルにある任意のノードです。 兄弟は同じタイプのノードである必要はありません-テキスト、要素、およびコメントのノードはすべて兄弟にすることができます。

Property Gets

previousSibling

Previous Sibling Node

nextSibling

Next Sibling Node

previousElementSibling

Previous Sibling Element Node

nextElementSibling

Next Sibling Element Node

兄弟プロパティは、すべてのノードを横断する一連のプロパティと、要素ノードのみの一連のプロパティがあるという点で、子ノードと同じように機能します。 `+ previousSibling `と ` nextSibling `は指定されたノードの直前または直後の次のノードを取得し、 ` previousElementSibling `と ` nextElementSibling +`は要素ノードのみを取得します。

`+ nodes.html `の例では、 ` ul +`の中央の要素を選択しましょう。

const tiger = ul.children[1];

JavaScript Webアプリとしてではなく、ゼロからDOMを作成したため、DOMには空白があるため、要素の兄弟プロパティを使用して前および次の要素ノードにアクセスする必要があります。

tiger.nextElementSibling.style.background = 'coral';
tiger.previousElementSibling.style.background = 'aquamarine';

このコードを実行すると、 `+ Hammerhead `の背景に ` coral `が適用され、 ` Great White `の背景に ` aquamarine +`が適用されます。

image:https://assets.digitalocean.com/articles/eng_javascript/dom/traverse-4.png [兄弟要素の変更]

兄弟プロパティは、親およびノー​​ドのプロパティと同様に、一緒に連鎖させることができます。

結論

このチュートリアルでは、すべてのHTMLドキュメントのルートノードにアクセスする方法と、親、子、および兄弟のプロパティを介してDOMツリーをウォークする方法について説明しました。

DOMの要素にアクセスする方法とこのチュートリアルで学んだことで、次のことができるはずです。 WebサイトのDOM内のノードに自信を持ってアクセスします。