DOM(Document Object Model)は、JavaScriptでWebページの見た目や動作を変更するための重要な概念です。 Webページに表示されるすべての要素やコンテンツは、DOMのツリー構造の中に配置されています。 JavaScriptを使用することで、DOMを操作してテキストや画像の変更、フォームの送信、クリックやマウスオーバーなどのイベントの制御など、様々なことができます。 このチュートリアルでは、DOMの基本的な概念や使い方を詳しく説明しています。 JavaScriptでWebページの操作に役立てたいと考えている方にとって、このチュートリアルは大変役立つことでしょう。

Wikipedia
Wikipedia
ウィキペディアDocument Object Modelの記事があります。

_

DOMの基本的な概念の説明編集

DOM(Document Object Model)とは、Webページのコンテンツや要素にアクセスするための仕組みであり、JavaScriptを使ってWebページを操作するための基本的な概念です。

DOMとは何か編集

DOMは、WebページのHTML要素を階層的なツリー構造で表現する方法です。これによって、JavaScriptを使用してWebページの要素にアクセスし、変更することができます。DOMは、ブラウザによって構築され、Webページの読み込み時に自動的に生成されます。

DOMツリーとは何か編集

DOMツリーは、Webページの要素を親子関係で階層的に表現したものです。WebページのHTML要素は、ルート要素(HTML要素)をルート(根)として、その子要素としてHEAD要素とBODY要素があります。さらに、BODY要素内には、テキスト、画像、リンクなどの要素が含まれます。このように、DOMツリーはWebページの要素を視覚的に表現することができます。

DOMのノードとは何か編集

DOMのノードとは、DOMツリーの中の要素や属性、テキストなど、Webページのすべての部分を表すオブジェクトです。ノードには、要素ノード、属性ノード、テキストノード、コメントノードなどがあります。要素ノードは、WebページのHTML要素を表し、属性ノードは、HTML要素の属性を表します。テキストノードは、HTML要素内のテキストを表し、コメントノードは、HTMLのコメントを表します。これらのノードには、JavaScriptを使ってアクセスし、変更することができます。

DOMへのアクセス方法の説明編集

DOMへのアクセス方法には、いくつかの方法があります。ここでは、代表的な5つの方法を紹介します。

getElementById()メソッド
getElementById()メソッドは、Webページ内の指定されたid属性を持つ要素を取得します。このメソッドは、一意のid属性を持つ要素を取得する場合に特に有用です。
const element = document.getElementById('example-id');
getElementsByClassName()メソッド
getElementsByClassName()メソッドは、指定されたクラス名を持つすべての要素を取得します。このメソッドは、複数の要素を取得する場合に特に有用です。
const elements = document.getElementsByClassName('example-class');
getElementsByTagName()メソッド
getElementsByTagName()メソッドは、指定されたHTMLタグ名を持つすべての要素を取得します。このメソッドは、指定されたHTMLタグ名のすべての要素を取得する場合に特に有用です。
const elements = document.getElementsByTagName('p');
querySelector()メソッド
querySelector()メソッドは、指定されたCSSセレクタに一致する最初の要素を取得します。このメソッドは、より柔軟な要素の取得を可能にするため、広く使用されています。
const element = document.querySelector('.example-class');
querySelectorAll()メソッド
querySelectorAll()メソッドは、指定されたCSSセレクタに一致するすべての要素を取得します。このメソッドは、複数の要素を取得する場合に特に有用です。
const elements = document.querySelectorAll('.example-class');
DOMとCSSセレクター
HTML+CSS+JavaScriptの技術基盤に基づくウェブコンテンツ制作において要素を指定する方法がCSS=CSSセレクターとDOM=getElementsBy*系メソッドと2つの異なる記法になってしましました。

このことは実装を複雑にし、誤解からバグの入り込む余地がありました。

この様な状況で、要素をCSSセレクターで指定できる jQuery などのフレームワークがもてはやされました。

実際のコードを見てみましょう

旧来の要素選択メソッド
getElementsByTagName("h1");
getElementsByClassName("className");
document.getElementById("sample");
getElementsByName("theName");

は、

jQueryの要素選択メソッド
$("h1");
$(".className");
$("#sample");
$([name="theName"]);

とCSSセレクターの書式で要素(へのラッパー)を得る等価な処理ができます。
ただこの方法では、ラッパーが間に入る続けるので冗長です[1]

この状況を憂慮して、DOMにもCSSセレクターを引数に要素を返すメソッドDocument.querySelector()とDocument.querySelectorAll()が追加されました[2]

CSSのセレクターの書式が使える新しい要素選択メソッド
document.querySelector("h1");
document.querySelectorAll(".className");
document.querySelector("#sample");
document.querySelector([name="theName"]);

最初に見つかった要素が必要なら Document.querySelector メソッドを、一致する全てを得るなら Document.querySelectorAll メソッドを使います。

従来のDOMは、ツリー構造から特定の要素(または要素コレクション)を要素・クラス・ID・name属性を区別して適切なメソッドを選ぶ必要があり煩雑で、しばしばバグの原因となりましたが、 Document.querySelectorメソッド及びDocument.querySelectorAllメソッドの登場で、 CSSと同じセレクターで記述することができるようになり「スタイルシートとスクリプトで要素を指定する手段が異なる」という捻じれ構造を是正することができました。

また、従来

LI要素全てに処理を行う
const li = document.getElementsByTagName("li");
for (let i = 0, len = li.length; i < len; i++) {
  // li[i]に対する処理
}

を、Arrayイテレータを使い

LI要素全てに処理を行う
const li = document.querySelectorAll("li");
li.forEach(el => /* elに対する処理 */)

と簡素に反復処理を行うことが可能となりました。


DOMの操作方法の説明編集

DOMを操作することで、Webページ上の要素を動的に変更できます。ここでは、代表的な3つの操作方法を紹介します。

ノードの追加、削除、置換編集

要素を追加、削除、または置換するには、次のようにDOMのメソッドを使用します。

要素の追加
const parent = document.getElementById('parent-id');
const child = document.createElement('div');
parent.appendChild(child);
要素の削除
const child = document.getElementById('child-id');
child.parentNode.removeChild(child);
要素の置換
const parent = document.getElementById('parent-id');
const newChild = document.createElement('div');
const oldChild = document.getElementById('old-child-id');
parent.replaceChild(newChild, oldChild);

ノードの属性の変更編集

要素の属性を変更するには、次のようにDOMのプロパティを使用します。

const element = document.getElementById('example-id');
element.setAttribute('src', 'new-image.png');

ノードのスタイルの変更編集

要素のスタイルを変更するには、次のようにDOMのプロパティを使用します。

const element = document.getElementById('example-id');
element.style.backgroundColor = 'red';

イベントの制御方法の説明編集

Webページ上でのユーザーのアクションやページの状態変化など、様々なイベントが発生します。JavaScriptを使ってこれらのイベントを制御することができます。

イベントの種類編集

代表的なイベントの種類をいくつか紹介します。

  • click:要素がクリックされたときに発生する。
  • mouseover:マウスが要素の上に移動したときに発生する。
  • keydown:キーボードのキーが押されたときに発生する。
  • load:ページや画像などが読み込まれたときに発生する。

addEventListener()メソッド編集

イベントを監視するには、次のようにDOMのメソッドを使用します。

const element = document.getElementById('example-id');
element.addEventListener('click', function() {
  console.log('clicked!');
});

上記の例では、example-idというIDを持つ要素がクリックされたときに、コンソールにclicked!という文字列が出力されます。

イベントハンドラ関数編集

イベントが発生したときに実行される関数を「イベントハンドラ関数」と呼びます。イベントハンドラ関数は通常、無名関数として定義されます。

const element = document.getElementById('example-id');
element.addEventListener('click', function() {
  console.log('clicked!');
});

または、以下のように、別の関数を呼び出すこともできます。

const element = document.getElementById('example-id');

function handleClick() {
  console.log('clicked!');
}

element.addEventListener('click', handleClick);

実践的な例の解説編集

ここでは、実践的な例をいくつか紹介し、JavaScriptでのDOM操作の実践的な活用方法を解説します。

フォームの送信編集

フォームの送信には、submitイベントを利用します。以下は、フォームが送信されたときに、入力された内容を取得する例です。

<form id="example-form">
  <input type="text" name="name" id="name-input">
  <input type="submit" value="Submit">
</form>

<script>
const form = document.getElementById('example-form');
form.addEventListener('submit', function(event) {
  event.preventDefault(); // フォームのデフォルト動作を停止する
  const nameInput = document.getElementById('name-input');
  console.log('name:', nameInput.value);
});
</script>

ボタンのクリックイベントの制御編集

ボタンのクリックイベントを利用して、何らかの処理を行うことができます。以下は、ボタンがクリックされたときに、メッセージを表示する例です。

<button id="example-button">Click me</button>

<script>
const button = document.getElementById('example-button');
button.addEventListener('click', function() {
  alert('Hello, world!');
});
</script>

マウスオーバーイベントの制御編集

マウスオーバーイベントを利用して、要素の表示や非表示を切り替えることができます。以下は、マウスが要素の上に乗ったときに、別の要素を表示する例です。

<div id="example-div">
  <p>Hello, world!</p>
  <p id="hidden-text" style="display: none;">You found me!</p>
</div>

<script>
const div = document.getElementById('example-div');
const hiddenText = document.getElementById('hidden-text');

div.addEventListener('mouseover', function() {
  hiddenText.style.display = 'block';
});

div.addEventListener('mouseout', function() {
  hiddenText.style.display = 'none';
});
</script>

ブラウザ間のDOMの違いについての解説編集

ブラウザごとのDOMの差異編集

ブラウザによってDOMの扱いが異なる場合があります。例えば、Internet Explorer 8以下では、getElementsByClassName()メソッドが使えないため、別の方法を使う必要があります。Firefoxでは、addEventListener()メソッドに対して、attachEvent()メソッドを使用する必要がある場合があります。

クロスブラウザ対応の方法の解説編集

クロスブラウザ対応するためには、以下のような方法があります。

  1. 特定のブラウザに対して、別途対応するコードを書く方法 例えば、Internet Explorer 8以下で使えないgetElementsByClassName()メソッドの代わりに、querySelectorAll()メソッドを使用することができます。
  2. ライブラリを使用する方法 ブラウザごとのDOMの差異を吸収するライブラリを使用することができます。代表的なライブラリとしては、jQueryやModernizrなどがあります。
  3. ブラウザのバージョンを判定する方法 ブラウザのバージョンによって処理を分けることで、クロスブラウザ対応することができます。ただし、メンテナンスが難しくなるため、できるだけ避けるべきです。
註記
ここでは、互換性を阻害する例として、あえてInternet Explorer 8以下に言及しましたが、Internet Explorer は2022年サポートが終了していますので、2023年4月現在では上記の配慮は不要です。

よく使われるライブラリの紹介編集

JavaScriptには多くのライブラリがあり、その中でもjQueryやReactはよく使われています。

jQueryの概要と使用方法編集

jQueryは、JavaScriptを簡単に扱えるようにするライブラリです。HTMLドキュメント内の要素を選択し、イベントを追加したり、要素のスタイルを変更したりすることができます。

以下は、jQueryを使用した単純な例です。

<!DOCTYPE html>
<html>
<head>
	<title>jQuery Example</title>
	<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
</head>
<body>
	<button id="btn">Click me!</button>
	<script>
		$(document).ready(function() {
			$("#btn").click(function() {
				alert("Hello, World!");
			});
		});
	</script>
</body>
</html>

この例では、jQueryの $ 関数を使用して document オブジェクトを選択し、ready メソッドを使用してページが読み込まれた後にコードを実行するように指定しています。そして、click メソッドを使用して btn 要素にクリックイベントを追加し、alert メソッドを使用して「Hello, World!」というメッセージを表示しています。

Reactの概要と使用方法編集

Reactは、Facebookによって開発されたJavaScriptライブラリで、ユーザーインターフェースの作成に特化しています。Reactは、仮想DOMを使用してパフォーマンスを最適化し、コンポーネントベースの開発に適しています。

以下は、Reactを使用した単純な例です。

<!DOCTYPE html>
<html>
<head>
	<title>React Example</title>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
</head>
<body>
	<div id="root"></div>
	<script>
		function App() {
			return (
				<h1>Hello, World!</h1>
			);
		}
		
		ReactDOM.render(
			<App />,
			document.getElementById('root')
		);
	</script>
</body>
</html>

この例では、App 関数を定義して、<h1> 要素を返します。そして、ReactDOM.render メソッドを使用して App 関数を root 要素にレンダリングしています。

よく使われるツールの紹介編集

Web開発でDOMを扱う際に、ブラウザの開発者ツールが非常に役立ちます。代表的なブラウザの開発者ツールとして、Chrome DevToolsとFirefox Developer Editionがあります。 これらのツールは、DOMの構造やスタイル、イベントの発生などをリアルタイムに確認することができます。

Chrome DevToolsのDOMパネルの解説編集

Chrome DevToolsのDOMパネルは、現在のページのDOMの構造を視覚的に表現したものです。 このパネルでは、DOMノードの階層構造をツリー形式で表示し、各ノードの属性やスタイルを編集することができます。 また、イベントのリッスンやスクリプトの実行も可能です。Chrome DevToolsのDOMパネルは、F12キーを押すことで開くことができます。

Firefox Developer EditionのDOMインスペクタの解説編集

Firefox Developer EditionのDOMインスペクタは、Chrome DevToolsのDOMパネルと同様の機能を持っています。 DOMノードの階層構造をツリー形式で表示し、各ノードの属性やスタイルを編集することができます。 Firefox Developer EditionのDOMインスペクタは、F12キーを押すことで開くことができます。 Firefox Developer Editionは、開発者向けの機能が豊富に備わっているブラウザであり、Web開発において高い評価を得ています。

DOM以外のドキュメントモデル編集

DOM以外にも、ドキュメントモデルにはいくつかの種類があります。

SAX (Simple API for XML)
XML文書を一行ずつ読み込み、要素を一つずつ処理する方法。
イベント駆動のため、メモリの使用量が少なく高速に処理できる。
要素の親子関係などの階層的な情報は保持しない。
JDOM (Java Document Object Model)
Javaで扱うためのDOMライブラリ。
DOMよりもシンプルなAPIで、より扱いやすい。
XML要素をJavaのオブジェクトとして扱うことができる。
LINQ to XML (Language Integrated Query to XML)
.NET Frameworkの一部で、XML文書を扱うためのAPI。
XMLをクエリ言語のように扱うことができる。
XML文書を.NETオブジェクトとして扱うことができる。
JsonML (JSON Markup Language)
JSON形式でXML文書を表現する方法。
データをJavaScriptのオブジェクトとして扱うことができる。
ドキュメントツリーを持たないため、SAXと同様に要素の階層関係を保持しない。

附録編集

チートシート編集

// ページ全体の読み込みが完了した時に実行される関数
window.addEventListener('load', function() {

  // 要素を取得する方法
  
  // IDを指定して要素を取得する
  const elementById = document.getElementById('element-id');
  
  // セレクタを使って要素を取得する
  const elementBySelector = document.querySelector('.element-class');
  
  // セレクタを使って複数の要素を取得する
  const elementsBySelectorAll = document.querySelectorAll('.element-class');
  
  // タグ名を使って要素を取得する
  const elementByTagName = document.getElementsByTagName('div');
  
  // クラス名を使って要素を取得する
  const elementsByClassName = document.getElementsByClassName('element-class');
  
  // 要素の属性を取得・変更する方法
  
  // 属性の値を取得する
  const attributeValue = elementById.getAttribute('data-attribute');
  
  // 属性の値を変更する
  elementById.setAttribute('data-attribute', 'new-value');
  
  // 要素のテキストを取得・変更する方法
  
  // 要素のテキストを取得する
  const elementText = elementById.textContent;
  
  // 要素のテキストを変更する
  elementById.textContent = 'new-text';
  
  // 要素のスタイルを変更する方法
  
  // スタイルプロパティを変更する
  elementById.style.backgroundColor = 'red';
  
  // 要素のクラスを変更する
  elementById.classList.add('new-class');
  elementById.classList.remove('old-class');
  
  // 要素を作成・追加する方法
  
  // 新しい要素を作成する
  const newElement = document.createElement('div');
  
  // 要素を追加する
  elementById.appendChild(newElement);
  
  // 要素を削除する
  elementById.removeChild(newElement);
  
  // イベントリスナーを追加する方法
  
  // クリックイベントを追加する
  elementById.addEventListener('click', function() {
    // クリックされた時に実行される処理
  });
  
});

用語集編集

  1. DOM (Document Object Model): HTMLやXMLドキュメントを表すためのオブジェクトの階層的な構造。JavaScriptを用いて、ドキュメント内の要素にアクセスや操作をすることができる。
  2. ノード (Node): DOMの要素であり、HTML要素、テキスト要素、コメントなどが含まれる。親子関係や兄弟関係などを持ち、階層的に構成される。
  3. 要素 (Element): HTML文書におけるタグに対応するDOMのノード。タグの種類に応じた属性を持つことができる。
  4. 属性 (Attribute): 要素に付加された情報であり、要素の属性として定義される。id、class、srcなどがある。
  5. CSSセレクタ (CSS Selector): CSSで用いられる要素を指定するための記述方法。要素名、クラス名、IDなどを用いて要素を指定することができる。
  6. コレクション (Collection): 複数の要素を持つオブジェクト。HTMLCollectionやNodeListなどがある。
  7. innerHTML: 要素内のHTMLを表すプロパティ。テキストやHTMLタグなどを含む。
  8. textContent: 要素内のテキストを表すプロパティ。HTMLタグを含まない。
  9. スタイルプロパティ (Style Property): CSSで定義されたスタイルを要素に適用するためのプロパティ。backgroundColor、colorなどがある。

脚註編集

  1. ^ このおかげでメソッドチェーンが使えるのですが。
  2. ^ DOM Living Standard::4.2.6. Mixin ParentNode -- The querySelector(selectors) method steps are to return the first result of running scope-match a selectors string selectors against this, if the result is not an empty list; otherwise null.

外部リンク編集