JavaScript | DOM 操作:テキスト・内容変更 – テキストと要素の違い

JavaScript JavaScript
スポンサーリンク

テキストと要素の違いとは何か

DOM は「要素ノード」と「テキストノード」でできています。要素ノードはタグ(div、p、span など)そのもので、属性やクラス、イベントを持てます。テキストノードは純粋な文字だけで、タグや属性はありません。ここが重要です:見た目や振る舞い(CSS・イベント)は要素が担当し、表示する文言はテキストが担当します。役割を分けることで、安全で壊れにくい UI が作れます。


要素ノードの特徴(構造・属性・イベントを持てる)

要素は「箱」そのもの

<div id="card" class="info" data-type="product">Apple</div>
<script>
  const card = document.getElementById("card");
  console.log(card.tagName);      // "DIV"(要素名)
  console.log(card.className);    // "info"(クラス)
  console.log(card.dataset.type); // "product"(data-* 属性)
  card.addEventListener("click", () => console.log("clicked")); // イベント登録
</script>
HTML

要素はタグ名、属性、クラス、スタイル、イベントリスナを持てます。ここが重要です:見た目(CSS)や動き(JS)は要素に紐づけ、テキストはその中身として扱います。


テキストノードの特徴(文字だけ、属性やイベントはない)

テキストは「中身の文字」

<p id="msg"></p>
<script>
  const msg = document.getElementById("msg");
  const text = document.createTextNode("こんにちは"); // テキストノードを生成
  msg.appendChild(text); // p 要素の中身として追加

  console.log(text.nodeType); // 3(Text)
  // text にクラスやイベントは付けられない
</script>
HTML

テキストノードは文字を保持するだけで、クラスやスタイル、イベントは持てません。ここが重要です:装飾や操作は必ず親の要素に対して行い、文字は textContent や createTextNode で入れます。


取得・走査での違い(children と childNodes、最初の子の扱い)

要素だけを扱うか、全ノードを扱うか

<ul id="list">
  <!-- コメント -->
  <li>A</li>
  <li>B</li>
  テキスト
</ul>
<script>
  const list = document.getElementById("list");

  console.log(list.children.length);   // 2(LI 要素だけ)
  console.log(list.childNodes.length); // 4(コメント・要素・テキストを含む)

  console.log(list.firstElementChild.tagName); // "LI"(要素限定の先頭)
  console.log(list.firstChild.nodeType);       // 8 or 3(コメント/テキストの可能性)
</script>
HTML

ここが重要です:UI ロジックは「要素限定」の API を使うのが安全です。children/firstElementChild/nextElementSibling を優先すると、空白やコメントでズレません。


テキストの入れ替えと HTML の展開(安全性と意図の違い)

テキストだけを安全に入れる

<h2 id="title"></h2>
<script>
  const title = document.getElementById("title");
  title.textContent = "ようこそ"; // タグを解釈せず、文字として表示(安全)
</script>
HTML

HTML を構造として挿入する

<div id="box"></div>
<script>
  const box = document.getElementById("box");
  box.innerHTML = "<b>強調</b> と <i>斜体</i>"; // タグが展開される(要注意)
</script>
HTML

ここが重要です:外部データやユーザー入力は常に textContent(または createTextNode)。innerHTML は固定テンプレートに限り、動的部分は必ずエスケープして混ぜます。安全性を最優先に。


イベントとスタイルは要素に付ける(テキストには付けない)

動き・見た目は親要素へ

<p id="line"><span id="name"></span> さん、こんにちは</p>
<script>
  const line = document.getElementById("line");
  const name = document.getElementById("name");

  name.textContent = "田中";              // 文字は安全に差し込む
  line.classList.add("greeting");          // 見た目は要素にクラスで
  line.addEventListener("click", () => {   // 動きも要素にイベントで
    line.classList.toggle("active");
  });
</script>
HTML

ここが重要です:テキストノードにイベントやクラスは付けられません。常に「要素に付ける」を徹底すると、設計がシンプルで壊れにくくなります。


部分更新のコツ(構造は要素で、内容はテキストで)

子要素を保ったまま文字だけ差し替える

<article class="card">
  <h3><span id="title-text"></span></h3>
  <p id="desc-text"></p>
</article>
<script>
  document.getElementById("title-text").textContent = "お知らせ";
  document.getElementById("desc-text").textContent  = "明日メンテナンスがあります。";
</script>
HTML

ここが重要です:構造は要素(固定)、可変部分はテキスト。この分離で、イベントが消えず、XSS の心配もなく、変更に強い UI になります。


解析・判定の違い(matches・closest は要素で使う)

要素に対するセレクタ判定・祖先探索

<div class="card"><button class="buy">購入</button></div>
<script>
  document.addEventListener("click", (e) => {
    const t = e.target;
    if (!(t instanceof Element)) return; // テキストノード対策

    if (t.matches("button.buy")) {
      const card = t.closest(".card");
      card.classList.add("purchased");
    }
  });
</script>
HTML

ここが重要です:matches/closest は「要素」に対して使います。イベントの target がテキストノードになることがあるため、必ず Element かどうかをチェックします。


実践例:メモ行の追加(構造は要素、文字はテキスト)

<ul id="notes"></ul>
<input id="input" placeholder="メモを入力">
<button id="add">追加</button>
<script>
  const notes = document.getElementById("notes");
  const input = document.getElementById("input");
  const add   = document.getElementById("add");

  add.addEventListener("click", () => {
    const text = input.value.trim();
    if (!text) return;

    const li = document.createElement("li");          // 要素(構造)
    li.appendChild(document.createTextNode(text));    // テキスト(内容)
    notes.appendChild(li);
    input.value = "";
  });
</script>
HTML

ここが重要です:createElement + createTextNode の組み合わせなら、外部入力でも“文字として”安全に表示できます。構造と内容を分けるのが定石です。


まとめ

要素は「箱」で、属性・クラス・イベント・スタイルを持てる。テキストは「中身の文字」で、装飾やイベントは持てない。取得や走査は要素限定の API(children/firstElementChild/matches/closest)を使い、内容の更新は textContent や createTextNode で安全に行う。HTML を展開する必要があるときだけ innerHTML を限定的に使い、動的部分は必ず文字として扱う。構造と内容の役割を明確に分離すると、セキュアで保守しやすい DOM 操作が身につきます。

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