DOMとは
Document Object Model(ドキュメントオブジェクトモデル)の略で、HTMLやXMLの文書を扱うためのAPIです。
DOMではHTMLやXMLのデータ内の要素をオブジェクトとして扱い、オブジェクトが階層的に組み合わされたものとして識別します。
ノード
DOMでは識別されたオブジェクトのことをノードと呼びます。
ノードにはいくつか種類があり、それぞれが役割を担っています。
ノードの種類 | 概要 |
---|---|
ドキュメントノード | HTML文書全体 |
要素ノード | HTMLタグ |
テキストノード | HTMLタグ以外のテキスト |
属性ノード | HTMLタグの属性(classやidなど) |
コメントノード | コメントアウトされたテキスト |
これらのノードが階層的に組み合わさり、木構造を形成したものをDOMツリーと呼びます。
階層構造
DOMではノードが組み合わさることで階層構造を形成します。
以下のようなコードがあったとします。
<html>
<head>
<title>sample</title>
<meta chareset="utf-8">
</head>
<body>
<p id="test">
<!--コメント-->
これは<strong>サンプルテキスト</strong>です。
</p>
</body>
</html>
階層構造で表すと下記のようになります。
Document
└ html
├ head
│ ├ 空白
│ ├ title
│ │ └ sample
│ ├ 空白
│ ├ meta
│ └ 空白
└ body
├ 空白
└ p ─ id
├ 空白
├ コメント
├ 空白
├ これは
├ strong
│ └ サンプルテキスト
├ です。
└ 空白
DOMツリーでは空白はテキストとして扱われ、空白ノードというテキストノードの一つとして分類されます。
DOM操作
ノードにはHTMLと同じように親子関係があります。
bodyタグを基準として考えると、htmlタグは、bodyの親ノードにあたり、headタグは兄弟ノード、pタグは子孫ノードにあたります。
プロパティ
ノードの参照方法として以下のプロパティがありますが、こちらのプロパティでは空白ノードを含めて参照してしまうため、効率があまり良くありません。
プロパティ | 概要 |
---|---|
parentNode | 親ノードへの参照。(参照先がDocumentオブジェクトの場合はnullを返す) |
childNodes | 子ノードへの参照。 |
firstChild | 最初の子ノード。(子ノードを持たない場合はnullを返す) |
lastChild | 最後の子ノード。(子ノードを持たない場合はnullを返す) |
nextSibling | 兄弟ノード内の次のノード。(次の兄弟ノードを持たない場合はnullを返す) |
previousSibling | 兄弟ノード内の一つ前のノード。(前の兄弟ノードを持たない場合はnullを返す) |
nodeType | ノードのノードタイプを返す。 |
nodeValue | テキストノードの値を返す。 |
nodeName | 要素ノードの要素名を返す。(pタグの場合はp) |
そのため、テキストノードを無視して要素ノードを取り出すためのプロパティがあります。
プロパティ | 概要 |
---|---|
parentElement | 親ノードへの参照。(参照先がDocumentオブジェクトの場合はnullを返す) |
children | 子要素ノードへの参照を格納するHTMLCollection |
firstElementChild | 最初の子要素ノード。(子要素ノードを持たない場合はnullを返す) |
lastElementChild | 最後の子要素ノード。(子要素ノードを持たない場合はnullを返す) |
nextElementSibling | 兄弟要素ノード内の次の要素ノード。(次の兄弟要素ノードを持たない場合はnullを返す) |
previousElementSibling | 兄弟要素ノード内の一つ前のノード。(前の兄弟要素ノードを持たない場合はnullを返す) |
childElementCount | 子要素ノードの数。 |
メソッド
上記のプロパティはdocumentを基準としてノードを取得しているためかなり不便です。
そのため任意の要素ノードを取得するメソッドがあります。
メソッド | 概要 |
---|---|
getElementById('id名') | 指定したid名と一致する要素ノードを取得 |
getElementsByClassName('クラス名') | 指定したクラス名と一致した要素をHTMLCollectionとして取得 |
getElementsTagName('タグ名') | 指定したタグ名と一致した要素をHTMLCollectionとして取得 |
getElementsByName('属性名') | 指定した属性名と一致した要素をNodeListとして取得 |
quelySelector('セレクタ') | 指定したセレクタと一致した要素の最初のひとつを取得 |
quelySelectorAll('セレクタ') | 指定したセレクタと一致した要素を格納したNodeListとして取得 |
HTMLCollectionとNodeListの違い
今まで何回か出てきたHTMLCollectionとNodeListですが、どちらも要素を配列のように格納したものですが、挙動が異なる点がいくつか存在します。
HTMLCollectionは動的、NodeListは静的
HTMLCollectionは後から要素が増減した場合、動的に反映されるのに比べて、NodeListは要素が後から増減しても反映されることはありません。
<ul id="list">
<li class="listitem">テキスト</li>
<li class="listitem">テキスト</li>
<li class="listitem">テキスト</li>
<li class="listitem">テキスト</li>
</ul>
const item = document.getElementsByClassName('listitem');
console.log(item); // => 4
//HTMLCollection
const newitem = document.createElement('li');
newitem.innerText = 'テキスト';
newitem.classList.add('listitem');
const list = document.getElementById('list');
list.appendChild(newitem);
console.log(item.length); // => 5
//NodeList
const newList = document.createElement('li');
newList.innerText = 'テキスト';
newList.classList.add('listitem');
const list = document.getElementById('list');
list.appendChild(newList);
console.log(item.length); // => 4
メソッドの違い
HTMLCollectionとNodeListでは、使用できるメソッドが異なります。
NodeListでは、forEachメソッドが使用できますが、HTMLCollectionに対しては使用できないといった違いがあります。