よく聞くけど説明できなかったDOMを整理する ― HTMLとJavaScriptの間にあるもの
はじめに
こんにちは、YSです。
今回は DOM について整理します。
DOMという言葉は、フロントエンドを触っているとかなりよく聞きます。
- DOMを操作する
- 仮想DOM
- DOMツリー
document.getElementById- ReactはDOMを直接触らない
ただ、いざ「DOMって何ですか?」と聞かれると、意外と説明が難しいです。
少なくとも自分は、最初うまく言語化できませんでした。
この記事では、DOMを 「HTMLをブラウザがJavaScriptから扱える形に変換したもの」 として整理してみます。
まずHTMLはただの文字列
Webページは、まずHTMLとして書かれます。
<html>
<body>
<h1>就活copilot</h1>
<p>ES管理を効率化するアプリです</p>
<button>開始する</button>
</body>
</html>
人間が見ると、
- 見出しがある
- 説明文がある
- ボタンがある
と分かります。
ただ、このHTMLは最初はただのテキストです。
ブラウザはこの文字列を読み取り、「これは見出し」「これは段落」「これはボタン」という形で解釈します。
その結果として作られるのがDOMです。
DOMとは
DOMは Document Object Model の略です。
ざっくり言うと、
HTMLを、JavaScriptから操作できるオブジェクトの形にしたもの
です。
ブラウザはHTMLを読み込むと、その内容をもとにDOMツリーを作ります。
document
└── html
└── body
├── h1
├── p
└── button
このように、HTMLの親子関係がツリー構造として表現されます。
つまりDOMは、
画面そのものというより、画面を作るためにブラウザが内部で持っている構造
と考えると分かりやすいです。
DOMがあると何ができるのか
DOMがあることで、JavaScriptからHTMLの要素を取得したり、内容を変えたりできます。
たとえば、次のHTMLがあるとします。
<h1 id="title">こんにちは</h1>
JavaScriptからこの要素を取得できます。
const title = document.getElementById("title");
そして、テキストを書き換えることもできます。
title.textContent = "こんばんは";
すると、画面上の表示も変わります。
こんにちは
↓
こんばんは
これは、JavaScriptがHTMLファイルそのものを書き換えているわけではありません。
ブラウザが作ったDOM上の要素を書き換えています。
その結果、画面の表示も更新されます。
HTMLとDOMは同じではない
ここが少し混乱しやすいところです。
HTMLとDOMは似ていますが、同じものではありません。
| 観点 | HTML | DOM |
|---|---|---|
| 何か | 書かれた文書 | ブラウザが解釈して作る構造 |
| 形式 | 文字列・ファイル | オブジェクト・ツリー |
| 扱うもの | 開発者が書くコード | ブラウザが内部で持つ構造 |
| JavaScript操作 | 直接ではない |
document 経由で操作できる |
HTMLは設計図に近いです。
DOMは、その設計図をブラウザが読み込んで、実際に扱える形にしたものです。
たとえば、HTMLに多少の省略があっても、ブラウザが補完してDOMを作ることがあります。
<table>
<tr>
<td>項目</td>
</tr>
</table>
このHTMLを書いたとしても、ブラウザのDOMでは tbody が補われることがあります。
<table>
<tbody>
<tr>
<td>項目</td>
</tr>
</tbody>
</table>
このように、HTMLとして書いた内容と、ブラウザが実際に持っているDOMは完全に一致しないことがあります。
DOM操作とは
DOM操作とは、JavaScriptからDOMを変更することです。
たとえば、以下のような操作です。
- 要素を取得する
- テキストを変更する
- classを付け替える
- 新しい要素を追加する
- 要素を削除する
- クリックイベントを登録する
例として、ボタンをクリックしたらメッセージを変える処理を書いてみます。
<p id="message">未送信です</p>
<button id="submitButton">送信する</button>
const message = document.getElementById("message");
const button = document.getElementById("submitButton");
button.addEventListener("click", () => {
message.textContent = "送信しました";
});
ボタンをクリックすると、DOM上の p 要素のテキストが変わり、画面も更新されます。
これがDOM操作です。
Reactを書いているとDOMを意識しにくい
ReactやNext.jsを書いていると、直接DOMを触る機会はそこまで多くありません。
たとえばReactでは、次のように状態を変えるだけで画面が更新されます。
import { useState } from "react";
export function SubmitMessage() {
const [message, setMessage] = useState("未送信です");
return (
<>
<p>{message}</p>
<button onClick={() => setMessage("送信しました")}>
送信する
</button>
</>
);
}
このコードでは、document.getElementById は出てきません。
textContent も直接変更していません。
それでも画面は更新されます。
これはReactが、状態の変化に応じて「どのDOMをどう更新するか」を裏側で考えてくれているからです。
つまりReactを書いていると、
DOMを直接操作する代わりに、状態を変えることで画面を更新する
という書き方になります。
仮想DOMとは何か
DOMと一緒によく聞く言葉に 仮想DOM があります。
仮想DOMは、ざっくり言うと、
本物のDOMを直接更新する前に、JavaScript上で持っておく軽量な設計図
です。
Reactは状態が変わったとき、いきなり本物のDOMを全部作り直すわけではありません。
まずJavaScript上で新しい画面の構造を作り、前の構造との差分を見ます。
そして、必要な部分だけ本物のDOMに反映します。
イメージとしては、
状態が変わる
↓
新しい仮想DOMを作る
↓
前の仮想DOMと比較する
↓
変わった部分だけ本物のDOMを更新する
という流れです。
細かい仕組みまで最初から理解する必要はありません。
まずは、
仮想DOMは、本物のDOM更新を効率よく行うために使われる中間的な表現
くらいで押さえておくとよさそうです。
DOMを一言で説明するなら
自分が説明するなら、こう言います。
DOMは、HTMLをブラウザが読み込んで、JavaScriptから操作できるツリー構造のオブジェクトとして表したものです。
もう少し噛み砕くなら、
HTMLは書いた文書で、DOMはブラウザがそれを解釈して作った操作可能な構造です。
という感じです。
面接や会話で聞かれたときは、ここまで言えればまず十分だと思います。
まとめ
DOMは、フロントエンドでよく聞くわりに、意外と説明しづらい言葉です。
- DOMは Document Object Model の略
- HTMLをブラウザが解釈して作るツリー構造
- JavaScriptからHTML要素を操作するための入り口になる
- HTMLとDOMは似ているが同じではない
- DOM操作とは、JavaScriptからDOMの要素を取得・変更すること
- ReactではDOMを直接触る代わりに、状態を変えて画面を更新する
- 仮想DOMは、本物のDOM更新を効率よく行うための中間的な表現
まずは、
DOM = HTMLをブラウザがJavaScriptから扱える形にしたもの
と理解しておくと、かなり見通しが良くなると思います。
Discussion