【JavaScript】そういうことか！DOM操作！（ドロップダウンメニューを作ってみた）

# はじめに
この記事はJSの学習を始めて1週間の初心者が学んだことを備忘録的に書いたものです。間違っている点などがあれば、コメントで教えていただけると幸いです(__)

本記事では、よく使うDOM操作についてまとめた上で、実際にドロップダウンメニューを作ってみようと思います！

# DOMとは
そもそも、DOMって何？って話なんですよね。。

現段階の私のイメージとしては、

**「HTMLの構造が格納されている箱」**

です。

DOM操作では、その箱の中身(HTML要素)に変化を加えることで、Webページを動的なものにしてくれます。

# DOM操作
DOM操作でよく使うメソッドを紹介していきます！

### 1. document.querySelector() , document.getElementById()
- **querySelector**
このメソッドはCSSセレクターを使ってHTML要素を取得できます。
ただし、一致する最初の要素だけを取得してくるため、一致するすべての要素を取得したいときは、**querySelectorAll**を使います。

- **getElementById**
このメソッドはid属性値を使って一致する要素を取得してきます。

### 2. Element.innerHTML
HTML要素の内容を取得または変更します。
### 3. Document.createElement() , Node.appendChild()
- createElement
新しい要素を作成します。
- appendChild
作成した要素を追加します。
### 4. Element.classList
要素内のクラスを操作します。
### 5. EventTarget.addEventListener()
イベントリスナーを追加します。

※イベントリスナー:あるイベントが発生したときに、それに応じて自身が書いたコードが実行される。if文みたいなイメ－ジ？主に以下のようなものがあります。
- マウスイベント (クリック、ホバーなど)
- キーボードイベント (キーを押す、離すなど)
- フォームイベント (入力、送信など)
- ウィンドウイベント (ロード、リサイズなど)

# ドロップダウンメニューを作ってみよう

### ドロップダウンメニューとは
最初はコンパクトな状態で表示され、クリックするとメニュー項目が展開(ドロップダウン)するウェブサイトでよくある表示です。

## 実際に作っていこう
```html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dropdown</title>
</head>

<body>
    <main>
        <ul class="menu">
            <li>
                <a href="">親メニュー1</a>
                <ul>
                    <li>子メニュー1</li>
                    <li>子メニュー2</li>
                    <li>子メニュー3</li>
                </ul>
            </li>

            <li>
                <a href="">親メニュー2</a>
                <ul>
                    <li>子メニュー1</li>
                    <li>子メニュー2</li>
                    <li>子メニュー3</li>
                </ul>
            </li>

            <li>
                <a href="">親メニュー3</a>
                <ul>
                    <li>子メニュー1</li>
                    <li>子メニュー2</li>
                    <li>子メニュー3</li>
                </ul>
            </li>
        </ul>
    </main>
</body>

</html>
```

```css:style.css
@charset "utf-8";

*,
*::after,
*::before {
  box-sizing: border-box;
}

a {
  text-decoration: none;
  color: black;
}

main {
  max-width: 1000px;
  width: 100%;
  margin: 50px auto;
  background-color: aqua;
  padding: 20px;
  border-radius: 5px;
}

.menu > li > a {
  display: block;
  padding: 10px;
  background-color: aquamarine;
}

.menu > li > ul >li {
  display: block;
  padding: 10px;
  background-color: azure;
}

.menu ul {
  display: none;
}

.menu ul.active {
  display: block;
}
```

上記のHTML,CSSファイルを使って作っていきます。

ここで、一つ確認しておいてほしいことがあります。

現在の画面
![スクリーンショット_24-3-2024_19501_127.0.0.1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638476/dabed0f9-b990-fa36-33c2-cda7700c3133.jpeg)

HTMLファイルの親メニュー1にactiveクラスを追加してみます。
```html:index.html
<li>
    <a href="">親メニュー1</a>
    <ul class="active">
        <li>子メニュー1</li>
        <li>子メニュー2</li>
        <li>子メニュー3</li>
    </ul>
</li>
```

すると、以下のように画面が変化します！
![スクリーンショット_24-3-2024_195045_127.0.0.1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638476/42394c22-29f2-ea55-06a1-b407fb164240.jpeg)

さて、なぜでしょうか？
```css:style.css
.menu ul {
  display: none;
}

.menu ul.active {
  display: block;
}
```
これは、ulタグにactiveクラスを付けたことで、そのulタグに```display:block```が効いて表示されるようになります。

これをJavaScriptで再現していきましょう！

まず初めに何をすべきか考えていきます。
1. 親メニューがクリックされる
2. クリックされた親メニューと同じliタグ内にあるulタグをactiveクラスを追加する(例えば、親メニュー1がクリックされたら親メニュー1の子要素が表示されるということ。)

### 1. 親メニューがクリックされる
```javascript:script.js
"use strict";

const parentMenu = document.querySelectorAll(".menu > li > a");

for (let i = 0; i < parentMenu.length; i++) {
    parentMenu[i].addEventListener("click", function (e) {
        e.preventDefault();
        console.log("親メニュー" + (i + 1) + "がクリックされました");
    });
}
```

上の行から順に何をしているのか説明していきます。

- 1行目：先述した```document.querySelectorAll()```メソッドを利用して、
menuクラス直下の```li```要素直下の```a```要素を配列で取得してきます。そして、それを```parentMenu```という変数に格納しています。

- 2行目：for文で```parentMenu```に格納されている各要素にアクセスしています。

- 3行目：先述した```EventTarget.addEventListener()```メソッドを利用して、いずれかの```parentMenu```の要素をクリックしたら起こるイベントを定義しています。

- 4行目：デフォルトのイベント(クリックしたら起こること)を防いでいます。

- 5行目：コンソール画面にクリックされた親メニューを表示しています。

これで親メニューそれぞれをクリックできるようになりました！

### 2. クリックされた親メニューと同じliタグ内にあるulタグをactiveクラスを追加する
```javascript:script.js
"use strict";

const parentMenu = document.querySelectorAll(".menu > li > a");

for (let i = 0; i < parentMenu.length; i++) {
    parentMenu[i].addEventListener("click", function (e) {
        e.preventDefault();
        //追加された行
        parentMenu[i].nextElementSibling.classList.toggle("active");
    });
}
```

- ```parentMenu[i]```：クリックされた親メニューの```a```要素を指します。
- ```nextElementSibling```：```a```要素の次の兄弟要素(ul要素)指します。
- ```classList.toggle("active")```：その兄弟要素(ul要素)のクラスに```active```クラスを追加、削除します。(activeクラスがついている状態でクリックされたらactiveクラスを削除し、activeクラスがついていない状態でクリックされたらactiveクラスを追加します。つまり、クリックするごとにメニューを閉じたり開いたりできます！)

これで、ドロップダウンメニューが完成です！

いかがでしたか？
JavaScriptは実装したことが目に見えてわかるのでとても楽しいですよね:relaxed:
次は、Reactなどを学んでみたいです！

## 余談(いざ何か作ろうとすると手が止まってしまう。。。)

手が止まらないようにするには、結論、今回のように、その機能を実装するためには何をすべきか細かく考えることがとてもだいじです。
私も初めは、何を作るにしても全く手が動きませんでした。。。
しかし、タスクを細分化することですべきことが明確になるとともに、タスクそれぞれは小さいので手も動きやすくなります！