JavaScript | ゼロからはじめるプログラミング、30日で基礎を学ぶJavaScript:Webページを操作できるようになる - Day16:DOM操作②

JavaScript JavaScript
スポンサーリンク

Day16 後半のゴール

後半では、createElement と appendChild を
「ただ要素を増やす道具」から
「小さなUIコンポーネントを組み立てる道具」にレベルアップさせます。

ここでつかみたいのは、この感覚です。

Day16 後半で意識したいポイント

1つの「まとまり」(カード・行・メモ)を、複数の要素で組み立てる

createElement と appendChild を“入れ子”にして、階層構造を作る


1つの「カード」を組み立てるイメージ

目標とする見た目

例えば、こんな「メモカード」を作りたいとします。

タイトル(太字)
本文(普通のテキスト)

HTML で書くならこうです。

<div class="card">
  <h2>タイトル</h2>
  <p>本文テキスト</p>
</div>

これを JavaScript で「その場で作って追加する」のが、
今回の後半のテーマです。

DOM構造として分解してみる

このカードは、DOM的にはこういう構造です。

div(親)
その子どもとして h2
その子どもとして p

つまり、

親となる div を作る
中に入れる h2 を作る
中に入れる p を作る
h2 と p を div に appendChild する
最後に div を画面上のどこかに appendChild する

という「入れ子の appendChild」が必要になります。


カード生成関数を作る

createElement と appendChild の“入れ子”パターン

まずは「タイトルと本文を受け取って、カード要素を返す関数」を作ります。

function createCard(titleText, bodyText) {
  const card = document.createElement("div");
  card.className = "card";

  const title = document.createElement("h2");
  title.textContent = titleText;

  const body = document.createElement("p");
  body.textContent = bodyText;

  card.appendChild(title);
  card.appendChild(body);

  return card;
}
JavaScript

ここでやっていることを分解すると、

div を作る(カードの“箱”)
h2 を作って textContent をセット
p を作って textContent をセット
h2 と p を card の子どもとして追加
最後に card 自体を返す

という流れです。

重要なのは、
「appendChild の対象が入れ子になっている」ことです。

card.appendChild(title);
card.appendChild(body);

これで、card の中に h2 と p がぶら下がった
小さな DOM の“島”ができあがります。


作ったカードを画面に追加する

親コンテナに appendChild する

次に、このカードを表示する「置き場」を用意します。

<div id="cardContainer"></div>

JavaScript では、こう使います。

const cardContainer = document.getElementById("cardContainer");

const card1 = createCard("最初のメモ", "これは最初のメモです。");
cardContainer.appendChild(card1);

const card2 = createCard("二つ目のメモ", "これは二つ目のメモです。");
cardContainer.appendChild(card2);
JavaScript

流れとしては、

createCard で「完成済みの div(カード)」を作る
cardContainer.appendChild で画面に参加させる

という二段階です。

createElement → appendChild を
「カードの中身を組み立てるため」にも使い、
「カード自体を画面に追加するため」にも使っている、
という二重構造になっています。


ボタンでカードを追加するミニアプリ

完成イメージ

ボタンを押すたびに、
「メモ1」「メモ2」「メモ3」…と
カードが下に増えていく小さなアプリを作ってみます。

HTML 全体

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Day16 DOM操作② 後半</title>
    <style>
      .card {
        border: 1px solid #ccc;
        padding: 8px;
        margin: 4px 0;
      }
    </style>
  </head>
  <body>
    <h1>メモカード追加アプリ</h1>
    <button id="addButton">メモを追加</button>
    <div id="cardContainer"></div>

    <script>
      const addButtonElement = document.getElementById("addButton");
      const cardContainerElement = document.getElementById("cardContainer");

      let count = 0;

      function createCard(titleText, bodyText) {
        const card = document.createElement("div");
        card.className = "card";

        const title = document.createElement("h2");
        title.textContent = titleText;

        const body = document.createElement("p");
        body.textContent = bodyText;

        card.appendChild(title);
        card.appendChild(body);

        return card;
      }

      addButtonElement.addEventListener("click", () => {
        count += 1;
        const card = createCard(
          `メモ ${count}`,
          `これは ${count} 件目のメモです。`
        );
        cardContainerElement.appendChild(card);
      });
    </script>
  </body>
</html>

重要なポイントの整理

createCard で「1つのカード」という“まとまり”を作っている
カードの中は、createElement と appendChild の入れ子で構成している
addButton のクリックイベントで、count を増やしつつカードを生成
cardContainer に appendChild して画面に追加している

ここまでできると、
「DOMを1要素ずついじる」のではなく、
「小さなコンポーネントとして組み立てて追加する」
という感覚に一歩踏み込めています。


ユーザー入力を使ったカード生成

入力フォーム付きのカード追加

もう少し実用寄りに、
ユーザーが入力したタイトルと本文でカードを作る例を見ます。

<input id="titleInput" type="text" placeholder="タイトル">
<br>
<textarea id="bodyInput" placeholder="本文"></textarea>
<br>
<button id="addButton">メモを追加</button>
<div id="cardContainer"></div>

JavaScript はこう書けます。

const titleInputElement = document.getElementById("titleInput");
const bodyInputElement = document.getElementById("bodyInput");
const addButtonElement = document.getElementById("addButton");
const cardContainerElement = document.getElementById("cardContainer");

function createCard(titleText, bodyText) {
  const card = document.createElement("div");
  card.className = "card";

  const title = document.createElement("h2");
  title.textContent = titleText;

  const body = document.createElement("p");
  body.textContent = bodyText;

  card.appendChild(title);
  card.appendChild(body);

  return card;
}

addButtonElement.addEventListener("click", () => {
  const title = titleInputElement.value;
  const body = bodyInputElement.value;

  if (title === "" || body === "") {
    return;
  }

  const card = createCard(title, body);
  cardContainerElement.appendChild(card);

  titleInputElement.value = "";
  bodyInputElement.value = "";
});
JavaScript

ここでのセキュリティ的に重要なポイントは、
ユーザー入力を textContent に入れていることです。

textContent は「文字として扱う」ため、
ユーザーがどんな文字列を入れても、
それが HTML やスクリプトとして実行されることはありません。

createElement + textContent + appendChild は、
「ユーザー入力を使って DOM を増やすときの安全な基本形」だと覚えておいてください。


ありがちなつまずきと対処

親に appendChild するのを忘れる

createElement で要素を作り、
中身まで設定したのに「画面に出ない」場合、
ほぼ確実に appendChild を忘れています。

チェックポイントはこうです。

どの親要素にぶら下げるのか決めているか
その親要素を getElementById などで取得しているか
最後に appendChild を呼んでいるか

「工場で作った部品を、ちゃんと組み立てラインに乗せたか?」
という視点で見直すと、ミスに気づきやすくなります。

親要素の取得に失敗している

親となるコンテナの id を間違えていると、
cardContainerElement が null になり、
appendChild でエラーになります。

安全に書くなら、こういうチェックも入れられます。

const cardContainerElement = document.getElementById("cardContainer");

if (!cardContainerElement) {
  console.error("id=\"cardContainer\" の要素が見つかりません。HTML を確認してください。");
} else {
  // ここに appendChild を含む処理を書く
}
JavaScript

「想定していた親要素が存在しないときに、そのまま進めない」
というのは、堅牢なコードを書くうえでとても大事です。


Day16 後半のまとめ

createElement は「新しい要素を作る工場」。
appendChild は「作った要素を、どこかの親の子どもとしてDOMツリーに参加させる」操作。

後半では、

複数の要素を組み合わせた「カード」を組み立てる
createElement と appendChild を入れ子にして階層構造を作る
カード生成関数を作って再利用する
ボタンでカードを追加するミニアプリを作る
ユーザー入力を使ってカードを生成する
親要素の取得ミスや appendChild 忘れといった典型的なバグを意識する

ところまで踏み込みました。

ここまで来たあなたは、
「既存のHTMLをいじる人」から、
「JavaScriptでHTMLを“生み出して構成する人”」に確実にステップアップしています。

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