DOMとは

## はじめに
最近JavaScriptの学習を始めて、基本的な文法などはスラスラ学習できていたのですが、DOMについての学習フェーズに入った際に苦戦したので、記事に起こして自分の考えをまとめていこうと思います。
## DOMについて
それではDOMについて解説していこうと思います。
DOMと聞いて最初に思いついたのは...
![61YcU-h4oUL._AC_SX679_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2956452/bca37ba1-4036-a84c-f254-edff88d26fe1.jpeg)
これですね。ジ○ン軍のモビル○ーツかな・・・？みたいな。
でも実際にはDOM(Document Object Model)の略で、**Webアプリケーションを作るのにHTMLを操作する**ものみたいです。
もっと端的にいうと、**JSからHTMLの要素にアクセスするための仕組み**です。
DOMは下の画像のようなツリー構造になってます。
[![Image from Gyazo](https://i.gyazo.com/f48f02d723c38be7293b5c55f7ca6cf5.png)](https://gyazo.com/f48f02d723c38be7293b5c55f7ca6cf5)
画像からわかるようにDOMは「ドキュメントオブジェクト」とも呼びます。

## DOMの役割
それでは次にDOMの役割について解説していきます。
突然ですが、普段Webサイトを閲覧している際に、以下のような体験をしたことはないでしょうか？
- ボタンを押したらボタンそのもののデザインが変わった。
- ページをスクロールすると広告のバナーが途中で表示された。
- 入力フォームで入力内容を間違えると「正しく入力してください」というようなエラーが表示された。

これらは全てDOMを使って実現されています。
DOMを使うことで上記のような動的な表現力を手に入れることができます。
それでは具体的にどんなことができるのかを簡単なコードを例としてみていきましょう。
今回は[こちら](https://codepen.io/pen/)のページを利用して学習を進めていきます。
以下の内容でHTMLファイルを保存します。
```html:DOM動作確認用のWebページ
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <div id="sample">オリジナルのテキストです</div>
  </body>
</html>
```
次に以下の内容でJavaScriptファイルに保存します。
```javascript:DOMを利用したテキストの書き換え
const tag = window.document.querySelector('#sample');
tag.textContent = 'テキストを書き換えます'
```
このコードを実行すると「オリジナルのテキストです」と表示されていたものが、「テキストを書き換えます」という表示に変化するはずです。
[![Image from Gyazo](https://i.gyazo.com/22c22016c35700cbac3d372b764406a1.png)](https://gyazo.com/22c22016c35700cbac3d372b764406a1)
このように**HTML要素をJavaScriptから操作する機能を提供する**のが**DOM**です。
ちなみにコードを書く際にはWindowを省略してdocumentから書くことが多いです。
以下のコードはどちらも同じ挙動になります。
```javascript
window.document.querySelect('#foo');
document.querySelect('#foo');
```
## 要素の検索
HTMLの要素を操作するには、まず操作対象となる要素を探す必要があり、その際に使用するのが`querySelector()`メソッドです。
```javascript:特定の要素を検索
document.querySelector(CSSセレクタ);
```
`querySelector()`は引数にCSSセレクタを渡すと、それと一致した最初の要素を返します。また、複数の要素と一致した場合は最初に一致した値を返します。
文章だと伝わりづらいかとも思うので実際に使ってみます。
```html:class属性の要素を持つWebページ
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <div class="sample">class 属性が sample 1個目</div>
    <div class="sample">class 属性が sample 2個目</div>
    <div class="sample">class 属性が sample 3個目</div>
  </body>
</html>
```
```javascript:class属性sampleの要素を検索
const element = document.querySelecor('.sample);
console.log(element);
```

それでは、実行結果を見てみましょう。
[![Image from Gyazo](https://i.gyazo.com/8cba9d088b8686c6f5290b9fb81d4e52.png)](https://gyazo.com/8cba9d088b8686c6f5290b9fb81d4e52)
上記のようにHTML要素を取得することができたはずです。
このように`querySelector()`を使うことで任意のHTML要素を取得することができます。
余談ですが、1つの要素だけではなく、すべての要素を取得したい場面もあると思います、そのような時には`querySelectorALL()`メソッドを使用します。
使い方は基本的に同じで、引数にCSSセレクタを渡します。

## 要素の変更
要素の変更をする方法を学ぶと、先ほど紹介したようなボタンの色が変わったり、スクロール中に広告を表示したりなど、操作に応じた見た目の変化を実装することができます。
それではまず指定した要素のテキストを変更してみます。テキストを変更する際は`textContent`プロパティを使用します。
```javascript:テキストの変更
要素.textContent = '変更したいテキスト'
```

```html:テキスト要素を持つWebページ
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <p>テキスト</p>
  </body>
</html>
```
```javascript:テキストの書き換え
const p = document.querySelector('p');
p.textContent
```
それでは実行してみます。
[![Image from Gyazo](https://i.gyazo.com/e1543afd30879b74fefaa1ee704f13ab.png)](https://gyazo.com/e1543afd30879b74fefaa1ee704f13ab)
上記のようにブラウザ上のテキストが変更されたかと思います。
HTML自身はさまざまな属性を持っていますが、その中でも頻繁に使用する要素といえばimg要素があると思います。
img要素では幅(width)や高さ(height)、ファイルの場所を指定(src属性)したりとさまざまな属性が絡み合って画像を表示しています。
こちらもDOMを使用して変更できます。
```javascript:属性の参照と変更
// 指定した属性の値を参照
要素.属性名

// 指定した属性の値を変更
要素.属性名 = '変更したい値';
```
それでは実際に使っていきます。
```html:画像要素を持つWebページ
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <img src="(フリー素材のURLを使用)" width="200" height="200">
  </body>
</html>
```
```javascript:画像要素のwidth属性を変更
const img = document.querySelector('img');
img.width = 200;
```
それでは実行してみます。
[![Image from Gyazo](https://i.gyazo.com/8b19d44425feafb0c23147373686a38e.png)](https://gyazo.com/8b19d44425feafb0c23147373686a38e)
画像の幅が変更されていれば成功です。

## 要素の作成
DOMではHTML内に書かれていない要素を追加することができます。
それが`createElement()`メソッドです。このメソッドに引数としてタグ名を渡すことで要素オブジェクトが作成されます。
```javascript:要素の作成
document.createElement('タグ名');
```
それではp要素のオブジェクトを作成してみましょう。
```javascript:要素を作成する
const element = document.createElement('p');
console.log(element);
```
実行してみます。
[![Image from Gyazo](https://i.gyazo.com/632e8655f6be4d1b4d7478685977a2fe.png)](https://gyazo.com/632e8655f6be4d1b4d7478685977a2fe)
きちんとp要素が作成されました。
しかし、作成されただけではブラウザに表示されません。
実際に表示させるにはさまざまなメソッドを使用する必要があります。

createElementで作った要素オブジェクトを実際にブラウザで表示するには`append()`というメソッドを使用します。append()は指定した要素を子要素として末尾に追加することができるメソッドです。
```javascript:要素を追加
親要素.append('追加要素');
```
それでは使ってみましょう。
```html:要素を追加するWebページ
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <div class="content">
      <p>最初の要素</p>
    </div>
  </body>
</html>
```
```javascript:子要素の末尾に要素を追加
const newElement = document.createElement('p');
newElement.textContent = '新規に追加';

const content = document.querySelector('.content');
content.append(newElement);
```
実行してみます。
[![Image from Gyazo](https://i.gyazo.com/be30eac977b3477b610af35259ad4a9f.png)](https://gyazo.com/be30eac977b3477b610af35259ad4a9f)
無事に要素が追加されました。
逆に子要素の先頭に追加するときは`prepend()`メソッド、
```javascript:構文
親要素.prepend(追加要素);
```
指定した要素の前後に追加する時は`before()`メソッド・`after()`メソッド
```javascript:構文
指定要素.before(追加要素);
指定要素.after(追加要素)
```
をそれぞれ使用していきます。
## 要素の削除
要素を削除する際は`remove()`メソッドを使用します。
```javascript:要素の削除
削除したい要素.remove();
```
```html:要素を削除するWebページ
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <div class="content">
      <!-- 下記の要素を削除したい -->
      <p class="first">最初の要素</p>
    </div>
  </body>
</html>
```
```javascript:要素を削除する
const firstElement = document.querySelector('.first');
firstElement.remove();
```
それでは実行してみます。
[![Image from Gyazo](https://i.gyazo.com/de3136e3302c874297f6ee134e148571.png)](https://gyazo.com/de3136e3302c874297f6ee134e148571)
表記がなくなっていれば成功です。

## 要素の置換
最後に要素を置き換える際に使用する`replaceWith()`メソッドについて説明していきます。
```javascript:要素の置換
置き換えたい要素.replaceWith(置き換える要素);
```
先ほど使用したHTMLのp要素を置換します。
```html:要素の置換をするWebページ
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <div class="content">
      <!-- 下記の要素を別の要素に置換したい -->
      <p class="first">最初の要素</p>
    </div>
  </body>
</html>
```
```javascript:要素を置換する
const newElement = document.createElement('p');
newElement.textContent = '置き換える要素';

const firstElement = document.querySelector('.first');
firstElement.replaceWith(newElement);
```
実行してみます。
[![Image from Gyazo](https://i.gyazo.com/4f3d0e00e4a0132f4eed9df25c29df5a.png)](https://gyazo.com/4f3d0e00e4a0132f4eed9df25c29df5a)
要素が置き換わりました。

## まとめ
以上のメソッドおよびプロパティをまとめると以下のようになります。
- 要素の探索 => `querySlector()`メソッド
- 要素の変更 => `textContent`プロパティ
- 要素の作成 => `createElement()`メソッド
- 要素の削除 => `remove()`メソッド
- 要素の置換 => `replaceWith()`メソッド

## 最後に
今回はJavaScriptのDOMについてまとめていきました。
Rubyを事前に勉強していたので、それぞれの文法などの学習にはそんなに時間がかからなかったもののDOMはちょっと特殊な感じがしたので、まあいい勉強になりました笑
イベントについても理解が不十分後頃があるので、後日まとめられたらいいなと思います。
余談ですが、もう少ししたら本格的にアプリ制作に取り組んでいく予定です。
自分の技術力がどれくらいあるか試せる場でもあるので楽しみです。


## 参考文献
https://jsprimer.net/

https://www.w3schools.com/js/js_htmldom.asp

https://www.shoeisha.co.jp/book/detail/9784798173269

https://bandai-hobby.net/item/4706/