🦍

JavaScriptのDOMについて(DOM操作の基礎から簡単なアプリ制作まで)

2024/06/02に公開

DOMとはJavaScriptとHTMLを繋げる仕組み・概念のことで、
特に、HTMLコーディングによるWebサイト制作などでJavaScriptで動きをつける、といった際にDOMの操作は必須の知識になると思います。
この記事では、備忘録を兼ねてJavaScriptのDOM操作に関して簡単に紹介し、最後には簡単なアプリを作成しようと思います。

DOMとは

正式にはDocument Object Modelといい、一言で言えばJavaScriptからHTML等のマークアップ言語で書かれたドキュメントにアクセスするための仕組みのことです。

HTMLでコーディングされたWebサイトでボタンクリック時に発火するアニメーションなど、ユーザーがアクションを起こすことでHTMLを操作する動きの部分をJavaScriptが担っています。
JavaScriptのDOMの操作により、HTMLを構成する要素に対してクラスを付与する、中身のテキストを削除する、書き換えるといった操作や、ボタンクリック時のアニメーションやフォーム入力時のイベントを設定する等、JavaScript側からHTMLを操作することができます。

なお、DOMの概念はJavaScript以外でも使用することができます。

要素を取得する

まずは操作の対象となる要素を取り出します。

getElementById()

一番シンプルなのがgetElementById()メソッドです。getElementById()は、指定されたidを持つ要素を取得するのに用います。

例として、<p id="result">要素に「テキスト」という文字列を入れる場合を紹介します。
document.getElementById()という構文を用いて、以下のように書きます。

html
<p id="result"></p>
javascript
const result = document.getElementById('result')
result.textContent = 'テキスト'

HTMLでidがresultの要素を取得し、resultという定数に代入しています。

querySelector(), querySelectorAll()

これらもgetElementById()と同様に要素を取得できるものですが、querySelector()とquerySelectorAll()はCSSセレクタを使って要素を取得します。
()の中の引数には要素やID、クラス名などを入れます。

querySelector()は取得した要素のうち、最初のひとつを返し、querySelectorAll()は該当するすべての要素を配列で返します。

html
<ul id="list">
    <li><a href="/hoge" class="btn">ボタン1</a></li>
    <li><a href="/moge" class="btn">ボタン2</a></li>
</ul>
javascript
// 最初の「ボタン1」だけ取得する
const firstBtn = document.querySelector('#list .btn')

// ボタン1、ボタン2をそれぞれ取得し、console.logでhref属性を出力する
const buttons = document.querySelectorAll('#list .btn')
for (const btn of buttons){
    console.log(btn.href)
}

要素を操作する

取得した要素に対して操作を行います。

innerHTML, textContent

要素のテキストを取得・設定するにはinnerHTML, textContentを用います。
例として、<p class="txt">要素内のテキストを取得します。

html
<p class="txt">テキストテキスト</p>
javascript
const txt =  document.querySelector('.txt')
console.log(txt.textContent)
// 「テキストテキスト」と出力される

txt.textContent = "変更しました"
// HTML上で <p class="txt">変更しました</p> に置き換わる

上記の例のように、textContentは取得した要素のテキストを取得したり、要素内のテキストを書き換えたりできます。

一方、innerHTMLは取得した要素の配下をHTML文字列として返します。
以下に例を載せます。

html
<div id="result_txt">
    <p class="txt">テキストテキスト</p>
</div>
javascript
const txt = document.querySelector('#result_txt')
console.log(txt.textContent)
// テキストテキスト と出力される

console.log(txt.innerHTML)
// <p class="txt">テキストテキスト</p> と出力される

上記のように、innerHTMLはHTML要素をそのまま取得・書き換えられる一方、textContentはテキストそのものを取得します。

classList

HTML要素にクラスを付与・削除したりします。
クラス付与にはclassList.add()、削除にはclassList.remove()を用います。
()の中に、付与・削除したいクラスを入れます。

html
<p id="txt" class="blue">タイトルタイトル</p>
javascript
const txt = document.querySelector('#txt')
txt.classList.add('red')
// redクラスを付与する
// <p id="txt" class="blue red">タイトルタイトル</p>

txt.classList.remove('blue')
// blueクラスを取り除く
// <p id="txt" class="red">タイトルタイトル</p>

createElement

今までは要素を取得してそれに対して操作を行ってきましたが、createElementは要素を0から作ります。
例として、li要素を作成し、定数addLiに代入します。

javascript
const addLi = document.createElement('li')
// <li></li> がaddLiに代入された

定数addLiにli要素が代入されましたが、現時点では作成したli要素をどこに追加するかを決めていません。
そこで、次に紹介するappendChildというものを用います。

appendChild

appendChildは、指定した要素の最後に要素を追加できます。
例として、以下のulタグの中に先ほど作成したliタグを追加します。
作成したliタグのテキストは「4」としました。

html
<ul class="list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
javascript
const list = document.querySelector('.list')
const addLi = document.createElement('li') // liタグを生成
addLi.textContent = '4' // 生成したliタグのテキストを4とする
list.appendChild(addLi) //生成したliタグをulタグの中に入れる

上記のコードにより、HTMLは以下のようになります。

html
<ul class="list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>

removeChildとremove

removeChildやremoveは、appendChildとは反対に指定した要素を削除できます。
両者の違いは以下の通りです。
removeChild: 親要素を取得し、その子要素に対して削除を行う
remove: 自分自身を消す

例として、先ほどの<ul class="list">から、一番最初のliタグを削除します。

html
<ul class="list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
javascript(removeChildの場合)
const list = document.querySelector('.list') // 親要素の取得
const deleteLi = document.querySelector('.list li') //削除する対象を取得
list.removeChild(deleteLi) //親要素から対象の子要素を削除する
javascript(removeの場合)
const deleteLi = document.querySelector('.list li') //削除する対象を取得
deleteLi.remove() //対象を削除する

この場合、どちらもHTMLは以下のようになります。

html
<ul class="list">
    <li>2</li>
    <li>3</li>
</ul>

addEventListener

最後に、「イベントハンドラ」の設定として、addEventListener()を紹介します。これはイベントを受け取るメソッドです。(JavaScriptにおけるイベントとは、ボタンクリック時やページ読み込み完了など、状態の変化を表します)
addEventListener()では、ボタンクリックやマウスホバーなどのイベントが起こった際にどんな処理を行うか、を書きます。

addEventListener()には引数を2つ設定し、1つ目にはイベントの種類、2つ目はその際に実行する関数を書きます。
例として、ボタンクリック時にアラートを表示させるコードを紹介します。

html
<button>クリックしてね</button>
javascript
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
    alert('クリックしました')
})

ボタンクリック時に「クリックしました」というアラート文がでます。

今回はクリック時にイベントを発火させたいため、第一引数でclickを設定しました。
第一引数にはclick以外にもいろいろなイベントを設定できます。
詳しくはこちらの記事がわかりやすかったです↓
https://kanlog.org/javascript-addeventlistener/

簡単なアプリを作ってみる(好きな映画リスト)

最後に、簡単なアプリを作成してみようと思います。
これを通じて、JavaScriptのDOM操作のイメージを深めることができれば幸いです。
好きな映画を入力して、リストを作成するアプリになります。

実際のコード

作成の流れ

このアプリでは、登録ボタンクリック時にinputタグの値(value)をリストに追加していくというものです。

作成の流れとして、以下のように作っていけばいいと思います。

  • 登録ボタンにaddEventListenerでクリック時のイベントを発火させる準備をする
  • 入力した値(inputタグのvalue)の取得
  • liタグを生成し、取得したinputタグのvalueをテキストとして埋め込む
  • 生成したliタグを<ul class="movieList"></ul>の中に入れる

要素の取得

まずはquerySelectorで登録ボタンを取得し、addEventListenerでクリック時に起こるイベントを作る準備をします。

javascript
const btn = document.querySelector('.submitBtn')
btn.addEventListener('click', () => {
    // ここに処理を書いていく
})

この中にコードを記述していけば、ボタンクリック時にそれが実行されるようになります。

入力した値の取得

querySelectorでinputタグを取得します。今回はinputタグそのものではなく、その入力値(value)が欲しいので、以下のようにします。

javascript
const btn = document.querySelector('.submitBtn')
btn.addEventListener('click', () => {
    // ここに処理を書いていく
    const input = document.querySelector('.inputTitle').value
})

定数inputにinputタグの入力値が代入されました。

新しいliタグを作り、親のulタグに追加する

定数inputにinputタグの入力値が代入されたため、createElementで新しいliタグを作ってtextContentで定数inputの値を埋め込みましょう。
そのようにして作成したliタグをappendChildで親の<ul>タグに追加してあげます。

javascript
const btn = document.querySelector('.submitBtn')
btn.addEventListener('click', () => {
    const input = document.querySelector('.inputTitle').value

    //liタグを作成し、ulの配下に追加する
    const ul = document.querySelector('.movieList') // 親の要素を取得
    const createLi = document.createElement('li') // liタグを生成する
    createLi.textContent = input // 生成したliタグのテキストを設定する
    ul.appendChild(createLi) // 生成したliタグを親のulタグに追加する
})

これで基本的な動きは完成です。最後に、ボタンをクリックしてリストに追加した後、次の入力をしやすいようにinputタグの中身(value)を空にしましょう。
inputタグの中身はdocument.querySelector('.inputTitle').valueでしたから、一連の動作の最後にこれを空文字にすればいいと思います。

javascript
const btn = document.querySelector('.submitBtn')
btn.addEventListener('click', () => {
    const input = document.querySelector('.inputTitle').value
    const ul = document.querySelector('.movieList')
    const createLi = document.createElement('li')
    createLi.textContent = input
    ul.appendChild(createLi)

    // inputタグの中身(value)を空にする
    document.querySelector('.inputTitle').value = ''
})

おまけ

これで完成でもいいのですが、今のままではコードが少々見にくいため、新しいliタグを作り親のulタグに追加する部分を関数にまとめてみます。
関数名はcreateLiとしました。
関数で書き出すことで、コードが見やすくなるだけでなく、「addEventListenerのこの部分でliタグを作っているんだな」とパッと見でわかりやすくなります。

javascript
const btn = document.querySelector('.submitBtn')
btn.addEventListener('click', () => {
    const input = document.querySelector('.inputTitle').value
    createLi(input) // 関数を呼び出す
    document.querySelector('.inputTitle').value = ''
})

// 関数にまとめる
const createLi = (value) => {
    const ul = document.querySelector('.movieList')
    const createLi = document.createElement('li')
    createLi.textContent = value
    ul.appendChild(createLi)
}

以上になります。

終わりに

今回作成したアプリでは、入力欄が空欄でもクリックできてしまいます。今後も学習を重ねることで、それを直していけたらいいなと思っています。

最後まで読んでいただきありがとうございました。

参考

【世界で70万人が受講】Web Developer Bootcamp 2023(日本語版)
改訂3版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで
https://webstyle.work/queryselector/
https://kanlog.org/javascript-addeventlistener/

Discussion