JavaScript フロントエンド開発入門 - 簡単Todoアプリを作ろう (２回目)

## はじめに

HI Engineer Collegeでは、実務未経験のエンジニアの方や、エンジニアに興味がある方を募集したおります、まずはお気軽にお問い合わせください。

※ (株)G&T（【内々定まで最短2週間】ゼロからしっかりじっくり研修☆20代活躍中！）

https://gat-company.com/

※ HI Engineer Collegeに興味あがある方はこちら（プログラミングを学習したい方）

https://hiengineer.jp/


## JavaScript フロントエンド開発入門 - 簡単Todoアプリを作ろう (全5回)

### 第2回：Todoアプリの見た目とDOM操作の基本

前回の第1回では、開発の準備としてHTMLファイルとJavaScriptファイルを作成し、ブラウザで簡単なJavaScriptコードを実行させるところまで行いました。

今回は、Todoアプリの基本的な見た目（UI）を作成し、JavaScriptからその画面上の要素を操作するための第一歩を踏み出します。

#### 前回の振り返り

* フロントエンドはユーザーが触れる部分を担当する
* 開発にはテキストエディタとブラウザが必要
* HTMLファイルから`<script>`タグでJavaScriptファイルを読み込む
* `console.log()`で開発者ツールのコンソールにメッセージを表示できる

#### TodoアプリのUIを考えよう

簡単なTodoアプリに必要なUI要素は何でしょうか？最低限、以下のものが必要になりそうです。

* **Todoの内容を入力する場所:** テキスト入力フィールド
* **Todoを追加するためのボタン:** ボタン
* **追加されたTodoを表示する場所:** リスト形式で表示

これらの要素をHTMLを使って配置していきます。

#### HTMLでUIの構造を作る

前回の `index.html` ファイルを編集して、TodoアプリのUI要素を追加しましょう。`<body>` タグの中に、見出しの下に以下のコードを追加してください。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>はじめてのTodoアプリ</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>

    <h1>私のTodoリスト</h1>

    <div class="todo-input-area">
        <input type="text" id="todo-text" placeholder="新しいTodoを入力">
        <button id="add-button">追加</button>
    </div>

    <ul id="todo-list">
        </ul>

    <script src="script.js"></script>
</body>
</html>
```

**変更点と解説:**

* `<link rel="stylesheet" href="style.css">`: CSSファイル（`style.css`）を読み込むためのタグを`<head>`内に追加しました。CSSについてはこの後すぐに解説します。
* `<div class="todo-input-area">`: 入力フィールドとボタンをまとめるための`div`要素を追加しました。`class`属性はCSSで要素を指定する際に便利です。
* `<input type="text" id="todo-text" placeholder="新しいTodoを入力">`: テキストを入力するための入力フィールドです。
    * `type="text"`: テキスト入力であることを指定します。
    * `id="todo-text"`: この要素に `todo-text` という識別名（ID）をつけました。JavaScriptから特定の要素を操作する際にこのIDを使います。IDはページ内でユニーク（重複しない）である必要があります。
    * `placeholder="新しいTodoを入力"`: 入力フィールドに何も入力されていないときに薄く表示されるヒントテキストです。
* `<button id="add-button">追加</button>`: Todoを追加するためのボタンです。
    * `id="add-button"`: このボタンにも`add-button`というIDをつけました。
* `<ul id="todo-list">`: Todoアイテムのリストを表示するための順不同リスト（Unordered List）要素です。
    * `id="todo-list"`: このリスト全体に`todo-list`というIDをつけました。
    * ``: これはHTMLのコメントです。ブラウザには表示されませんが、コードのどこに何が表示されるかをメモしておくのに役立ちます。ここに後ほどJavaScriptでTodoアイテムを追加していきます。

この状態で `index.html` をブラウザで開くと、入力フィールドと「追加」ボタン、「私のTodoリスト」見出しの下に何も表示されていないリストが表示されるはずです。まだCSSがないので、見た目は素っ気ないですが、UIの構造ができました。

#### CSSで簡単なスタイリングをする

次に、見た目を少し整えるためにCSSファイルを作成します。`style.css` という名前でファイルを作成し、以下のコードを記述してください。

```css
body {
    font-family: sans-serif;
    margin: 20px;
    background-color: #f4f4f4;
}

h1 {
    color: #333;
}

.todo-input-area {
    margin-bottom: 20px;
}

#todo-text {
    padding: 8px;
    margin-right: 5px;
    border: 1px solid #ccc;
    border-radius: 4px;
}

#add-button {
    padding: 8px 15px;
    background-color: #5cb85c;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

#add-button:hover {
    background-color: #4cae4c;
}

#todo-list {
    list-style: none; /* リストの黒丸を消す */
    padding: 0;
}

#todo-list li {
    background-color: #fff;
    padding: 10px;
    margin-bottom: 5px;
    border: 1px solid #ddd;
    border-radius: 4px;
}
```

**CSSの解説:**

* CSSは、HTML要素がどのように表示されるかを定義するための言語です。
* `セレクタ { プロパティ: 値; }` という形式で記述します。セレクタはどのHTML要素にスタイルを適用するかを指定します。
    * `body`, `h1`: HTMLのタグ名を直接セレクタとして指定しています。
    * `.todo-input-area`: `class="todo-input-area"` という属性を持つ要素を指定しています。クラスセレクタは要素の前にドット(`.`)をつけます。
    * `#todo-text`, `#add-button`, `#todo-list`: `id="..."` という属性を持つ要素を指定しています。IDセレクタは要素の前にシャープ(`♯`)をつけます。IDはページ内で一意なので、特定の要素をピンポイントで指定できます。
    * `#add-button:hover`: ボタンにマウスカーソルを乗せたときのスタイルを指定します。（擬似クラスというものです）
    * `#todo-list li`: `#todo-list` というIDを持つ要素（`<ul>`）の中にある `<li>` 要素を指定します。
* `font-family`, `margin`, `padding`, `color`, `background-color`, `border`, `border-radius`, `cursor`, `list-style` などは、要素の見た目を制御するための様々なプロパティです。それぞれの意味はコード内のコメントや、Web検索で調べると詳しく解説されています。

`style.css` を保存し、再度 `index.html` をブラウザで開いてみてください。先ほどより少し見やすい見た目になったはずです。

#### JavaScriptからHTML要素を取得する（DOM操作の基本）

さて、見た目はできましたが、このままでは何も動きません。入力フィールドに入力したテキストを取得したり、「追加」ボタンがクリックされたことを検知したりするには、JavaScriptからHTMLの要素にアクセスする必要があります。

Webページは、ブラウザがHTMLファイルを読み込むと「DOM (Document Object Model)」という構造に変換されます。DOMは、HTMLの各要素をJavaScriptなどのプログラムから操作できるようにしたものです。木構造のようなイメージです。

JavaScriptからDOM上の要素を取得するには、いくつかの方法があります。今回はよく使う2つの方法を紹介します。

1.  **`getElementById()`:** 指定したIDを持つ要素を1つ取得します。IDはページ内で一意であるべきなので、特定の要素を確実に取得したい場合に便利です。
2.  **`querySelector()`:** 指定したCSSセレクタに一致する最初の要素を1つ取得します。より柔軟な要素の指定が可能です。

前回の `script.js` ファイルを開き、以下のコードを追記してみましょう。（前回の `console.log` と `alert` は消しても構いません。）

```javascript
// IDを使って要素を取得する
const todoInput = document.getElementById('todo-text');
const addButton = document.getElementById('add-button');
const todoList = document.getElementById('todo-list');

// 取得した要素をコンソールに表示して確認
console.log("入力フィールドの要素:", todoInput);
console.log("追加ボタンの要素:", addButton);
console.log("Todoリストの要素:", todoList);

// querySelectorを使って要素を取得することもできる
const addButtonQuery = document.querySelector('#add-button');
console.log("querySelectorで取得した追加ボタン:", addButtonQuery);

const inputAreaDiv = document.querySelector('.todo-input-area');
console.log("querySelectorで取得した入力エリアのdiv:", inputAreaDiv);

// querySelectorAllを使うと、指定したセレクタに一致する全ての要素を取得できる（今回は使いませんが参考までに）
// const listItems = document.querySelectorAll('#todo-list li');
// console.log("リストアイテム全て:", listItems);
```

**コードの解説:**

* `document`: ブラウザが表示しているHTMLドキュメント全体を表すオブジェクトです。DOMの最上位に位置します。
* `document.getElementById('...')`: `document`オブジェクトのメソッドで、指定されたIDを持つ要素を取得します。
* `document.querySelector('...')`: `document`オブジェクトのメソッドで、指定されたCSSセレクタに一致する最初の要素を取得します。IDを指定する場合は`#`、クラスを指定する場合は`.`をセレクタの前に付けます。
* `const`: 変数を宣言するためのキーワードです。一度代入すると、後から別の値を再代入することはできません。（`let`もありますが、今は`const`を基本に使いましょう。）ここで取得したHTML要素を後で利用するために変数に代入しています。
* 取得した要素を `console.log()` で出力して確認しています。ブラウザの開発者ツールで確認してみてください。`<input id="todo-text">` のような形で要素そのものが表示されるはずです。

#### イベント処理の基本（ボタンクリックを検知する）

画面上の要素がクリックされたり、入力内容が変わったりといった「イベント」が発生したときに、JavaScriptで何らかの処理を実行させたい場合があります。今回のTodoアプリでは、「追加」ボタンがクリックされたときに、入力フィールドのテキストを取得してリストに追加する処理を行いたいですね。

JavaScriptでイベントを処理するには、**イベントリスナー**という仕組みを使います。特定の要素に対して、「このイベントが発生したら、この関数（処理のまとまり）を実行してください」と「聞く」（listenする）ように設定するイメージです。

イベントリスナーを設定するには、要素オブジェクトの `addEventListener()` メソッドを使います。

`addButton` 変数にイベントリスナーを設定してみましょう。先ほどの `script.js` ファイルのコードに続けて、以下を追記してください。

```javascript
// 追加ボタンがクリックされたときに実行される処理を設定する
addButton.addEventListener('click', function() {
    console.log("追加ボタンがクリックされました！");
    // TODO: ここにTodoを追加する処理を書く
});

// function() { ... } の部分は、イベント発生時に実行したい処理をまとめた関数です。
// このような名前のない関数を「無名関数」と呼び、イベントリスナーによく使われます。
```

**コードの解説:**

* `addButton.addEventListener('click', ...)`: `addButton`という要素にイベントリスナーを設定しています。
* `'click'`: これはイベントの種類を指定しています。「クリック」イベントが発生したときに処理を実行したいという意味です。他にも `'mouseover'` (マウスが乗ったとき)、`'input'` (入力内容が変わったとき) など様々なイベントの種類があります。
* `function() { ... }`: イベントが発生したときに実行される関数を指定します。この中に、ボタンがクリックされたときに行いたい処理を記述します。

`script.js` を保存し、`index.html` をブラウザで開き、開発者ツールのConsoleタブを開いた状態で「追加」ボタンをクリックしてみてください。

Consoleに「追加ボタンがクリックされました！」というメッセージが表示されるはずです。これは、JavaScriptがボタンのクリックイベントを正しく検知し、指定した関数が実行されたことを意味します。

これで、Todoアプリの見た目を作成し、JavaScriptから画面上の要素を取得し、さらにボタンのクリックを検知できる状態になりました。次のステップは、入力フィールドのテキストを取得して、実際にTodoリストにアイテムを追加する処理を実装することです。

#### まとめ

今回は、TodoアプリのUIをHTMLで作成し、CSSで基本的なスタイリングを行いました。そして、JavaScriptからこれらのHTML要素を取得するためのDOM操作の基本と、要素のイベント（クリックなど）を検知するためのイベントリスナーについて学びました。

* HTMLで入力フィールド (`<input>`)、ボタン (`<button>`)、リスト (`<ul>`) を配置する
* CSSで要素の見た目を整える
* `id`属性や`class`属性は、JavaScriptやCSSから要素を指定する際に便利
* `document.getElementById()` や `document.querySelector()` でHTML要素をJavaScriptから取得できる
* `addEventListener()` で要素にイベントリスナーを設定し、特定のイベント発生時に処理を実行できる

これで、Todoアプリの機能を実装するための土台ができました。

---

**次回予告:** 第3回では、いよいよ入力フィールドのテキストを取得し、新しいTodoアイテムとしてリストに追加するJavaScriptコードを実装します。

---
お疲れ様でした！もし分からない点があれば、遠慮なく質問してください。