JavaScriptのDOMとイベント:入力・追加・削除ができるメモ一覧を作る
JavaScriptで入力・追加・削除ができるメモ一覧を実装。DOM取得、createElement、submitイベント、textContent、フォーカスの扱いを学びます。
第4回では、ブラウザーの入力欄とボタンをJavaScriptから扱います。HTML要素を取得し、イベントに応じて新しい要素を作る流れを確認します。Reactなどのフレームワークを使わない小さなメモ一覧です。
HTMLの構造を作る
index.htmlを保存する
新しい作業用フォルダーへindex.htmlを保存します。入力欄はラベルと関連付け、結果の件数を通知する領域を用意します。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JavaScriptのメモ一覧</title>
</head>
<body>
<main>
<h1>メモ一覧</h1>
<form id="memo-form">
<label for="memo-input">メモ</label>
<input id="memo-input" name="memo" required maxlength="100">
<button type="submit">追加</button>
</form>
<p id="status" role="status">0件のメモ</p>
<ul id="memo-list"></ul>
</main>
<script type="module" src="./app.js"></script>
</body>
</html>
moduleとしてスクリプトを読み込む
type="module"を指定して読み込みます。モジュールスクリプトは通常、HTMLの解析後に実行されるため、先に書いた要素を取得できます。Node.jsの例と違い、このコードはブラウザー上で実行します。
イベントでDOMを更新する
app.jsを作成する
同じフォルダーにapp.jsを保存します。ユーザーが入力したメモはtextContentで表示し、HTMLとして解釈しません。
const form = document.getElementById('memo-form');
const input = document.getElementById('memo-input');
const list = document.getElementById('memo-list');
const status = document.getElementById('status');
if (!form || !input || !list || !status) {
throw new Error('必要なHTML要素がありません。');
}
function updateStatus() {
status.textContent = `${list.children.length}件のメモ`;
}
form.addEventListener('submit', (event) => {
event.preventDefault();
const text = input.value.trim();
if (!text) {
status.textContent = '空白だけのメモは追加できません。';
input.focus();
return;
}
const row = document.createElement('li');
const label = document.createElement('span');
const removeButton = document.createElement('button');
label.textContent = text;
removeButton.type = 'button';
removeButton.textContent = '削除';
removeButton.setAttribute('aria-label', `${text}を削除`);
removeButton.addEventListener('click', () => {
row.remove();
updateStatus();
input.focus();
});
row.append(label, ' ', removeButton);
list.append(row);
input.value = '';
updateStatus();
input.focus();
});
preventDefaultで送信時の移動を止める
フォーム送信時の標準動作を止め、このページ内でメモを追加します。クリックイベントだけでなくsubmitを使うため、入力欄からEnterキーでも操作できます。
textContentとinnerHTMLを区別する
textContentは文字として表示します。たとえば<strong>大事</strong>と入力しても、太字のHTMLにはなりません。ユーザー入力をそのままinnerHTMLへ入れると、意図しないHTMLとして扱う危険があるため、この用途では使いません。
ローカルサーバーで開く
HTTP経由で表示する
Python 3が使える環境なら、作業フォルダーで次を実行します。file://で開く方法はモジュールの読み込み制約があるため、HTTPで確認します。
python3 -m http.server 8080 --bind 127.0.0.1
ブラウザーでhttp://localhost:8080/を開きます。サーバーを止めるときはターミナルでCtrl+Cを押します。
操作を確認する
- メモを追加すると、一覧と件数が増えます。
- 空欄はブラウザーの必須入力チェック、空白だけはJavaScript側で拒否します。
- 削除すると件数が減り、入力欄へフォーカスが戻ります。
- HTMLに見える文字列を入力しても、文字として表示されます。
- 再読み込みするとメモは消えます。この例は保存機能を持ちません。
実装を広げるときの注意
DOMとデータの役割を整理する
この小さな例ではDOMを一覧の状態として使っています。並び替えや永続化が必要になったら、配列をデータの本体として保持し、そのデータからDOMを更新する構成を検討します。
イベント登録の寿命を考える
今回はページの寿命と同じ期間だけフォームを使います。画面を何度も初期化する構成では、同じ要素への二重登録を避け、不要になったイベントを解除する設計が必要です。
参考資料と次の学習
非同期処理へ進む
次はPromise・async/await・fetchで、時間のかかる処理と失敗を扱います。