2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおけるDOM設計戦略:動的構築・イベント構造・パフォーマンスと責務の分離

Posted at

概要

DOM設計とは「HTMLを操作する」ことではない。
それは**構造・意味・操作・効率を統合する「UIの根幹設計」**である。

JavaScriptによってDOMを生成・制御する際、再描画、構造破壊、イベントの過剰結合といった問題が頻発する。
本稿では、それらを未然に防ぐための責任あるDOM設計戦略を提示する。


1. DOM構築は「意味単位」で行う

function createUserCard(user) {
  const card = document.createElement('div');
  card.className = 'user-card';

  const name = document.createElement('h2');
  name.textContent = user.name;

  const email = document.createElement('p');
  email.textContent = user.email;

  card.append(name, email);
  return card;
}
  • ✅ 「UIパーツ」をコンポーネント関数で定義
  • ✅ DOMの直接生成でも意味単位で分離する

2. 動的要素の責務を「構築・挿入・破棄」に分離

function insertUserList(users) {
  const list = document.createElement('ul');
  for (const user of users) {
    const item = document.createElement('li');
    item.textContent = user.name;
    list.appendChild(item);
  }
  document.querySelector('#container').replaceChildren(list);
}
  • ✅ 「生成」と「挿入」は別関数に → テストしやすくなる
  • replaceChildren()フラッシュ的更新

3. DOMイベント設計との分離

function bindButton(el, callback) {
  el.addEventListener('click', callback);
}
  • ✅ UI構築とイベント登録を分離して設計
  • ✅ 複数イベント登録を構造化できる
function bindEvents(el, events) {
  for (const [type, handler] of Object.entries(events)) {
    el.addEventListener(type, handler);
  }
}

4. パフォーマンス設計:再描画と再検索の最小化

  • ✅ DOMツリー更新はまとめて1回
  • DocumentFragmentを活用して仮想構築 → 挿入
const frag = document.createDocumentFragment();
for (const data of items) {
  const el = document.createElement('li');
  el.textContent = data;
  frag.appendChild(el);
}
list.appendChild(frag);

5. 意味と構造の分離:データ属性の活用

<button data-user-id="u01">詳細</button>
btn.dataset.userId; // → "u01"
  • ✅ DOMに意味を埋め込むのではなく、data- で分離*
  • ✅ アプリ構造とUI構造の結合を緩やかに保てる

6. DOMの破棄とガーベジ設計

  • ✅ 必ずイベントリスナーを解除する
function destroy(el) {
  el.remove();
}
  • ✅ Webアプリでは DOM残存 + イベント残存 → メモリリークを引き起こす

→ ✅ 「構築」「破棄」「再利用」のライフサイクル関数を分離して設計


設計判断フロー

① そのDOMは意味単位で構成されているか? → UI部品化へ

② DOMの構築とイベントが混在していないか? → 分離して責務明確化

③ 再描画を毎回DOMに適用していないか? → Fragment化 or replaceChildren

④ UIとロジックが結合していないか? → data-*で分離、ロジックは別層に

⑤ 破棄処理を忘れていないか? → destroy関数とremoveEventListener

よくあるミスと対策

innerHTML += を多用して毎回再評価・再構築が発生

→ ✅ DOM APIを用いた構築と挿入に分離


❌ 1つの関数でDOM構築・挿入・イベント登録・削除まで一括処理

→ ✅ 責務ごとの分離によりテスト性と再利用性を向上


❌ 破棄したはずのDOMにイベントが残留

→ ✅ removeEventListener + remove() を忘れずに


結語

DOMとは「UIの器」ではない。
それは意味・操作・振る舞いの集合体であり、構造そのものである。

  • 生成は意味単位にし
  • 振る舞いは責務で分離し
  • 表示は一括で最小化し
  • 破棄まで設計する

JavaScriptにおけるDOM設計とは、
“UIの構造を保ち、意味を壊さず、振る舞いを統合する”という設計戦略である。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?