「ボタンを動的に追加したら、クリックイベントが効かなくなった」
「配列を更新して再レンダリングしたら、イベントが消えた」
TypeScriptやJavaScriptでDOM操作を学び始めると、誰もが一度はぶつかる壁です。
私自身、これまで肉体労働中心の仕事をしてきましたが、未経験からIT企業への転職が決まり、TypeScriptを学ぶことになりました。
正直、最初は「イベントリスナーって、ボタンに直接つけるだけじゃないのか?」という状態でした。
しかし実際にToDoリストのようなUIを作ってみると、
「なぜイベントデリゲーションが必要なのか」
「なぜ配列を更新するとイベントが消えるのか」
という疑問に直面します。
この記事では、TypeScriptでイベントデリゲーションが必要になる理由と、実際のコードをもとにした実装イメージを、初心者目線で整理します。
結論から言うと、「UIを作り直す前提の設計」にイベントデリゲーションは必須です。
TypeScriptでイベントデリゲーションが必要な理由
そもそもイベントデリゲーションとは何か
イベントデリゲーションとは、
子要素に直接イベントを付けず、親要素にまとめてイベントを付与する方法です。
クリックされた要素を event.target から判別することで、
動的に追加・削除される要素にも対応できるようになります。
これは、静的なHTMLだけを扱っているときには、なかなか実感しづらい考え方です。
配列の再レンダリングでイベントが消える理由
ToDoリストのようなアプリでは、
- タスクを配列で管理
- 配列をもとにDOMを作り直す
という流れがよく使われます。
今回のコードでも、以下のように 一度すべての要素を削除してから再生成 しています。
document.querySelectorAll("p").forEach((p) => p.remove());
この時点で、もし各ボタンに直接 addEventListener を付けていた場合、
DOMを削除した時点でイベントも一緒に消えます。
つまり、
「見た目は同じボタンが再生成されているが、以前のボタンとは別物」
という状態になります。
この問題を避けるために使うのが、イベントデリゲーションです。
実装例で理解するイベントデリゲーション
親要素にイベントを付与する
今回のコードでは、ToDoリスト全体を包む div#all_list にイベントを設定しています。
all_l.addEventListener('click',(e)=>{
const comp = e.target as HTMLElement;
const idNum = Number(comp.id.replace("comp-", ""));
comp_task(idNum);
},false);
この書き方のポイントは次の通りです。
- クリックイベントは 親要素1ヶ所だけ
- 実際に押されたボタンは
e.targetから取得 idの文字列を加工して、処理対象を特定
どのボタンが押されるかわからない時のID取得
イベントデリゲーションでは、
「次にどのボタンが押されるか分からない」
という前提で設計します。
そのため、ボタン作成時に ルールのあるid を付けています。
comp_btn.id = `comp-${Arr[i].id}`;
dele_btn.id = `dele-${Arr[i].id}`;
そしてクリック時に、文字列を加工して数字部分を取り出します。
const idNum = Number(comp.id.replace("comp-", ""));
この書き方を覚えると、
- 完了ボタン
- 削除ボタン
- 動的に増える要素
すべてを1つのイベントで制御できるようになります。
DOMを全削除して再描画する設計
今回のコードでは、表示更新のたびに以下の流れを取っています。
- 既存のDOMをすべて削除
- 配列の状態をもとにDOMを作成
- 親要素にまとめたイベントで操作
これは一見すると乱暴に見えますが、
状態(配列)と表示(DOM)を分離する という点で、とても重要な考え方です。
Reactなどのライブラリが内部で行っている考え方にも近く、
「UIは状態の結果として作られるもの」という感覚を掴みやすくなります。
オブジェクトと型定義が効いてくる場面
今回のToDoリストでは、タスクをオブジェクトで管理しています。
type task = {
id: number;
theme: string;
done: boolean;
}
この型を定義しておくことで、
- タスクの構造が明確になる
doneの true / false が一目でわかる- イベント処理時に意図しない値を防げる
といったメリットがあります。
イベントデリゲーションはDOM操作の話ですが、
その裏ではオブジェクトと配列設計が非常に重要 だと実感しました。
まとめ
TypeScriptでイベントデリゲーションを使う理由は、
単に「便利だから」ではありません。
- 配列を更新してDOMを再生成する
- UIを状態の結果として扱う
- イベントが消える問題を防ぐ
これらを自然に解決するための設計です。
未経験からTypeScriptを学んで感じたのは、
イベントデリゲーションは「テクニック」ではなく「考え方」 だということです。
小さなToDoリストでも、この考え方を押さえておくと、
今後ReactやVueを学ぶ際にも理解が一気に楽になります。

コメント