はじめに
就活ブルーなももみんです。
DOMツリーを勉強するにょ💻
復習
DOMは 木構造である。(何の捻りもなくDOMツリー)
1日目の記事: DOMを学ぶ1~DOMとは何か~
今回の内容
DOMツリーを構成する ノード とは何か。
ノードとは何か
HTMLを書くとき、人間は要素を考える。<div>、<p>、<span>とか。(文章を紙に書くときと結局は同じ)
DOMにとって、HTMLの要素 = ノードの一種
ノード(Node) = DOMツリーを構成する最小単位
すべてのノードはNodeインターフェース(共通の基本的な設計)を実装していて、共通のプロパティとメソッドを持つ。
node.nodeType // ノードの種類を示す数値
node.nodeName // ノード名(要素名、"#text"など)
node.nodeValue // テキストノードの値(要素ではnull)
node.textContent // ノード内のテキスト
node.parentNode // 親ノード
node.childNodes // 子ノードのNodeList
node.firstChild // 最初の子ノード
node.lastChild // 最後の子ノード
node.previousSibling // 前の兄弟ノード
node.nextSibling // 次の兄弟ノード
node.ownerDocument // 所属するDocument
node.appendChild(child) // 子ノードを末尾に追加
node.insertBefore(new, ref) // refの前にnewを挿入
node.removeChild(child) // 子ノードを削除
node.replaceChild(new, old) // oldをnewで置換
node.cloneNode(deep) // ノードを複製
node.contains(other) // otherを含むか
node.hasChildNodes() // 子ノードがあるか
node.normalize() // 連続するテキストノードを結合
⬇️ メモ
https://developer.mozilla.org/ja/docs/Web/API/Node
12種類のノードタイプ
12種類のノードタイプが定義されている。
各タイプには数値が割り当てられており、nodeTypeプロパティで確認できる。
| 定数名 | 値 | 説明 |
|---|---|---|
| ELEMENT_NODE | 1 | 要素ノード |
| ATTRIBUTE_NODE | 2 | 属性ノード(非推奨) |
| TEXT_NODE | 3 | テキストノード |
| CDATA_SECTION_NODE | 4 | CDATAセクション(XML) |
| ENTITY_REFERENCE_NODE | 5 | 実体参照(非推奨) |
| ENTITY_NODE | 6 | 実体(非推奨) |
| PROCESSING_INSTRUCTION_NODE | 7 | 処理命令 |
| COMMENT_NODE | 8 | コメントノード |
| DOCUMENT_NODE | 9 | ドキュメントノード |
| DOCUMENT_TYPE_NODE | 10 | ドキュメントタイプノード |
| DOCUMENT_FRAGMENT_NODE | 11 | ドキュメントフラグメント |
| NOTATION_NODE | 12 | 記法(非推奨) |
この中で、1(要素)、3(テキスト)、8(コメント)、9(ドキュメント)、11(フラグメント)の5種類について調べる。
ELEMENT_NODE(要素ノード)
HTMLタグに対応するノードタイプ。
要素ノードはElementインターフェースを実装する。
// 要素の取得
element.querySelector('.child'); // 子要素を1つ取得
// クラス操作
element.classList.add('active'); // クラスを追加
// 属性操作
element.getAttribute('href'); // 属性の値を取得
// コンテンツ操作
element.textContent; // テキストを取得・設定
// スタイル操作
element.style.display = 'none'; // インラインスタイルを設定
⬇️ メモ
https://developer.mozilla.org/ja/docs/Web/API/Element
HTML要素は、さらにHTMLElementインターフェースを実装する。
const div = document.createElement('div');
console.log(div instanceof HTMLDivElement); // true
console.log(div instanceof HTMLElement); // true
console.log(div instanceof Element); // true
console.log(div instanceof Node); // true
⬇️ メモ
https://developer.mozilla.org/ja/docs/Web/API/HTMLElement
ElementとHTMLElement
ElementはSVGやXMLの要素も含む。
HTMLElementはHTML特有のプロパティ(dataset、hiddenなど)も持つ。
TEXT_NODE(テキストノード)
要素の「中」にあるテキストに対応するノードタイプ。
テキストノードはTextインターフェースを実装する。
<p>あいうえお</p>
p (ELEMENT_NODE)
└─ "あいうえお" (TEXT_NODE)
TEXT_NODE(空白テキストノード)
HTMLの改行やインデントも、テキストノード。
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
ul (ELEMENT_NODE)
├─ "\n " (TEXT_NODE) ← 改行とインデント
├─ li (ELEMENT_NODE)
│ └─ "Item 1" (TEXT_NODE)
├─ "\n " (TEXT_NODE) ← 改行とインデント
├─ li (ELEMENT_NODE)
│ └─ "Item 2" (TEXT_NODE)
└─ "\n" (TEXT_NODE) ← 改行
COMMENT_NODE(コメントノード)
HTMLコメントもDOMに存在する。
<div>
<!-- This is a comment -->
<p>Content</p>
</div>
div (ELEMENT_NODE)
├── "\n " (TEXT_NODE)
├── <!-- This is a comment --> (COMMENT_NODE)
├── "\n " (TEXT_NODE)
├── p (ELEMENT_NODE)
│ └── "Content" (TEXT_NODE)
└── "\n" (TEXT_NODE)
DOCUMENT_NODE(ドキュメントノード)
documentオブジェクト自体。
DOMツリーのルートに位置する。
console.log(document.nodeType); // 9
console.log(document.nodeName); // "#document"
console.log(document.documentElement); // <html>要素
ドキュメントノードはDocumentインターフェースを実装している。
要素の作成やクエリの起点となる。
document.createElement('div');
document.createTextNode('Hello');
document.getElementById('myId');
document.querySelector('.myClass');
⬇️ メモ
http://developer.mozilla.org/ja/docs/Web/API/Document
DOCUMENT_TYPE_NODE(ドキュメントタイプノード)
<!DOCTYPE html>に対応するノード。
「標準モード」でレンダリングするよう指示する役割。
DOCUMENT_NODEとDOCUMENT_TYPE_NODE
DOCUMENT_NODE = DOMツリー全体を管理するコンテナに対応するノード。
DOCUMENT_TYPE_NODE =<!DOCTYPE html>という宣言そのものを表すノード。
DOMは文書の『『すべて』』をノードとして表現する仕様である。
DOCUMENT_FRAGMENT_NODE(ドキュメントフラグメント)
DOMツリーに属さない、一時的なコンテナ(のノード)。
複数の要素をまとめて追加したいときに使う。
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
// 100個のliを1回の操作で追加
document.querySelector('ul').appendChild(fragment);
フラグメント自体は消え、中身だけがDOMに追加される。
ノードの継承関係
DOMのインターフェースは、階層的な継承関係を持つ。
EventTarget
└─ Node
├─ Document
├─ DocumentFragment
├─ DocumentType
└─ Element
└─ HTMLElement
├─ HTMLDivElement
└─ ...
すべてのノードはEventTargetを継承しているため、イベントリスナーを登録できる。
まとめ
DOMを学ぶとjsに対する印象が変わる。
DOMを学ぶと世界が広がる。
参考文献
- DOM Standard - Node interface - WHATWG
- MDN Web Docs - Node - Mozilla
- MDN Web Docs - Node.nodeType - Mozilla
- MDN Web Docs - DocumentFragment - Mozilla