JavaScript | DOM 操作:ノード操作 – createElement

JavaScript
スポンサーリンク

createElement とは何か

createElement は、JavaScript で新しい HTML 要素を“ゼロから”作るためのメソッドです。たとえば div、button、img、li など、タグ名を渡すだけで未配置の要素が生成されます。ここが重要です:作った直後の要素はまだ画面にありません。属性や中身、イベントを設定してから、親ノードへ追加して初めて表示されます。


基本の流れ(作る → 中身と属性をセット → 画面へ追加)

要素を作る

const card = document.createElement("div"); // まだ DOM に入っていない
JavaScript

作成直後は“ただのオブジェクト”。ID、クラス、テキストなど、必要な情報を与えます。

属性・クラス・テキストを設定する

card.id = "user-42";                 // プロパティでも OK
card.setAttribute("data-role", "user");
card.classList.add("card", "is-new"); // クラスの追加
card.textContent = "こんにちは!";      // 安全にテキストを入れる
JavaScript

ここが重要です:テキストは textContent を使うと安全です。innerHTML は“HTMLを解析して差し込む”ため、ユーザー入力をそのまま入れると危険になりやすいです。

画面へ追加する

document.body.appendChild(card); // ここで初めて表示される
JavaScript

appendChild は末尾に追加します。先頭に入れたいなら prepend、兄弟の前後なら before/after を使えます。


中身の組み立て(子要素・画像・リンク・ボタン)

子要素を作って入れ子にする

const title = document.createElement("h3");
title.textContent = "プロフィール";

const avatar = document.createElement("img");
avatar.src = "/img/user-42.png";
avatar.alt = "ユーザーのアイコン";

const actions = document.createElement("div");
const btn = document.createElement("button");
btn.textContent = "フォロー";
actions.appendChild(btn);

// 親にまとめて追加
card.append(title, avatar, actions); // append は複数引数OK
JavaScript

ここが重要です:append は Node と文字列を混ぜて渡せます。複数追加を一度でできるため、コードが短くなります。

イベントを付ける

btn.addEventListener("click", () => {
  btn.disabled = true;
  btn.textContent = "フォロー済み";
});
JavaScript

ここが重要です:作ったその場でイベントを付けてから DOM に入れると、追加後すぐに期待通り動作します。


挿入位置のコントロール(前後・入れ替え・削除)

兄弟の前後に挿入

const note = document.createElement("p");
note.textContent = "最新の更新情報";
card.before(note);  // card の“前”に挿入
// card.after(note); // card の“後”に挿入
JavaScript

既存の子を置き換える・まとめて差し替える

const list = document.getElementById("items");
const fresh = document.createElement("li");
fresh.textContent = "新項目";
list.replaceChildren(fresh); // 子を全部消して fresh のみに
JavaScript

削除する

card.remove(); // 親から切り離され画面から消える
JavaScript

ここが重要です:remove は親を意識せずに消せるため、クリーンアップが簡単です。


効率よく差し込む(DocumentFragment とバッチ更新)

多数の要素はフラグメントでまとめて

const frag = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
  const li = document.createElement("li");
  li.textContent = `項目 ${i}`;
  frag.appendChild(li);
}
document.getElementById("list").appendChild(frag); // 一括で挿入
JavaScript

ここが重要です:1つずつ DOM に足すと再計算が多く重くなります。Fragment で“まとめて作って、まとめて挿入”が定石です。

読む→書くの順でパフォーマンス最適化

スタイルやサイズを取得してから、まとめて createElement と append を行いましょう。ここが重要です:計測と更新を交互に繰り返すとレイアウト再計算が増えます。読む処理と書く処理を“塊”にするだけで体感が軽くなります。


テンプレートの活用(複雑な構造を安全・高速に)

<template> から複製して埋める

<template id="tpl-card">
  <article class="card">
    <h3 class="title"></h3>
    <img class="avatar" alt="">
    <button class="follow">フォロー</button>
  </article>
</template>
HTML
function renderUser(user) {
  const tpl = document.getElementById("tpl-card");
  const node = tpl.content.cloneNode(true); // 深い複製
  node.querySelector(".title").textContent = user.name;
  const img = node.querySelector(".avatar");
  img.src = user.avatar; img.alt = `${user.name}のアイコン`;
  node.querySelector(".follow").addEventListener("click", () => {/*…*/});
  document.getElementById("root").appendChild(node);
}
JavaScript

ここが重要です:template は画面に描画されず、“構造の雛形”として安全に使えます。cloneNode(true) でイベント以外のすべてが複製されるため、あとからイベントだけ付ければ効率的です。


セキュリティと安全な文字列化(textContent を基本に)

ユーザー入力は必ず文字として扱う

const msg = document.createElement("p");
msg.textContent = userInput; // 安全(HTMLがそのまま文字になる)
JavaScript

ここが重要です:innerHTML にユーザー入力を直接入れない。HTML片が必要なら、サーバー側のサニタイズや信頼できるテンプレートを使い、クライアントはできる限り textContent で差し込む癖をつけましょう。


実践例(通知トースト、ロード中ボタン、リスト差し込み)

通知トーストを生成・自動消去

function toast(text, kind = "info") {
  const t = document.createElement("div");
  t.className = `toast toast-${kind}`;
  t.textContent = text;
  document.body.append(t);
  setTimeout(() => t.remove(), 2000);
}
toast("保存しました", "success");
JavaScript

ここが重要です:create → 設定 → append → 時限 remove の型を覚えると、使い捨て UI が簡単に作れます。

ロード中にボタンを無効化して文言変更

async function doSend(btn) {
  btn.disabled = true;
  btn.textContent = "送信中…";
  try { await new Promise(r => setTimeout(r, 800)); }
  finally {
    btn.disabled = false;
    btn.textContent = "送信";
  }
}
const btn = document.createElement("button");
btn.textContent = "送信";
btn.addEventListener("click", () => doSend(btn));
document.body.append(btn);
JavaScript

ここが重要です:状態は“単一情報源”。視覚(文言)、操作不可(disabled)を同じロジックで切り替えます。

リストに行を差し込む(先頭・末尾・任意位置)

const list = document.getElementById("todo");
function addItem(text, where = "end") {
  const li = document.createElement("li");
  li.textContent = text;
  if (where === "start") list.prepend(li);
  else if (where === "before" && list.firstElementChild) list.firstElementChild.before(li);
  else list.append(li);
}
addItem("牛乳を買う", "start");
JavaScript

ここが重要です:prepend/append/before/after を使い分けると、複雑な insertBefore を使わず直感的に配置できます。


よくある落とし穴と回避策

作っただけでは表示されない

createElement 直後のノードは“未挿入”。必ず親へ append/insert して画面に出します。

innerHTML 乱用で脆弱になる

ユーザー入力や未知の文字列は textContent。HTMLを差し込みたいときはテンプレートやサニタイズ済みの信頼データを使います。

1つのノードを“複数箇所”へは挿入できない

DOM ノードは“唯一”。同じノードを二度 append すると移動になります。複製したいなら cloneNode(true) を使います。

大量挿入で重くなる

DocumentFragment や append の一括追加、読む→書くの順序最適化で軽くできます。可能ならスクロール領域は仮想化(表示件数を絞る)も検討します。


まとめ

createElement は「要素を作り、意味と中身を与え、所定の場所に挿す」ための基本メソッドです。テキストは textContent、属性は setAttribute/プロパティ、イベントは addEventListener、挿入は append/prepend/before/after、複数は DocumentFragment、複雑な構造は template+cloneNode が定石。安全性(innerHTML の扱い)とパフォーマンス(まとめて挿入)を押さえれば、初心者でも意図通りの動的 UI を快適に構築できます。

タイトルとURLをコピーしました