0Pricing
Frontend Academy · レッスン

要素の作成と追加

createElement、setAttribute、append、removeを使って、DOM構造を動的に構築・変更します。

「要素の作成と追加」はCoddyKit上の無料Frontend Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはFrontend Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Frontend Academyコースには全4レッスンが含まれています。

createElement

document.createElement(tagName) はメモリ上に新しい要素を作成します。まだ DOM には追加されていません。その後、プロパティを設定してツリーに追加します。

const btn = document.createElement('button');
btn.textContent = 'Click Me';
btn.classList.add('btn-primary');
btn.setAttribute('type', 'button');
// btn is in memory, not yet in the page

appendとappendChild

parent.append(child) は、ノードまたは文字列を parent の子要素の末尾に追加します。appendChild は古い同等の方法ですが、append のほうが柔軟で、複数のノードや文字列を受け取れます。

const list = document.querySelector('ul');
const item = document.createElement('li');
item.textContent = 'New item';
list.append(item); // adds to end of list

prepend、before、after

parent.prepend()は先頭に追加します。element.before()は要素の前に挿入します。element.after()は要素の後に挿入します。

const header = document.querySelector('.card-header');
const icon = document.createElement('img');
icon.src = 'icon.svg';
header.prepend(icon); // icon goes before all other children

const divider = document.createElement('hr');
header.after(divider); // divider goes after the header

insertAdjacentHTML

element.insertAdjacentHTML(position, htmlString)は、既存のコンテンツを置き換えずに、指定した位置へHTMLを挿入します。位置には、'beforebegin'、'afterbegin'、'beforeend'、'afterend'があります。

const container = document.querySelector('.list');
container.insertAdjacentHTML('beforeend', `
  <li class="item">
    <span class="name">Alice</span>
  </li>
`);
// Still avoid with user input — XSS risk

cloneNode

element.cloneNode(true)は、すべての子要素を含む要素のディープコピーを作成します。浅いコピーを作成する場合はfalseを渡します。テンプレート要素の複製に便利です。

const template = document.querySelector('.card-template');
const clone = template.cloneNode(true);
clone.querySelector('.card-title').textContent = 'New Card';
container.append(clone);

removeChildとremove()

element.remove()はDOMから要素を削除します。古い形式のparent.removeChild(child)も機能します。削除した要素も、変数から参照したり、再び追加したりできます。

const item = document.querySelector('.to-delete');
item.remove(); // clean modern syntax

replaceWith

oldElement.replaceWith(newElement)は、DOM内の古い要素を新しい要素に置き換えます。古いreplaceChildパターンよりも便利です。

const old = document.querySelector('.old-banner');
const fresh = document.createElement('div');
fresh.className = 'new-banner';
fresh.textContent = 'Updated!';
old.replaceWith(fresh);

一括挿入のためのDocumentFragment

DocumentFragmentは、DOM内には存在しない軽量なコンテナです。その中にサブツリーを構築してから、1回の操作で追加します。これにより、N回ではなく1回だけリフローが発生します。

const fragment = document.createDocumentFragment();
users.forEach(user => {
  const li = document.createElement('li');
  li.textContent = user.name;
  fragment.append(li);
});
// One DOM write:
document.querySelector('ul').append(fragment);

<template>要素

HTMLの<template>要素には、JavaScriptで複製するまでレンダリングされないマークアップを保持します。文字列を組み立てたり、表示中の要素を複製したりするよりも適しています。

<template id="card-tpl">
  <div class="card">
    <h3 class="card-title"></h3>
    <p class="card-body"></p>
  </div>
</template>

プロパティと属性の設定

要素のプロパティ(el.href、el.src、el.value)は、値を設定する最も直接的でパフォーマンスの高い方法であることが多いです。属性(setAttribute)は、対応するDOMプロパティがないカスタム属性やARIA属性に適しています。

// Property (preferred for standard HTML attributes):
img.src = '/photo.webp';
link.href = '/about';

// setAttribute (for ARIA and custom attributes):
button.setAttribute('aria-expanded', 'true');
div.setAttribute('data-index', '3');

ユーザーコンテンツでinnerHTMLを避ける

ユーザーが提供したデータから要素を構築する場合は、HTML文字列を組み立ててinnerHTMLを使用するのではなく、必ずDOMメソッド(createElement、textContent、setAttribute)を使用してください。ユーザー入力をHTML文字列に埋め込むことは決してしないでください。

// DANGEROUS:
container.innerHTML = `<p>${userComment}</p>`;

// SAFE:
const p = document.createElement('p');
p.textContent = userComment;
container.append(p);

クイックチェック

100回のリフローを発生させずに、<ul>へ100個のリスト項目を追加する必要があります。最適な方法はどれでしょうか。

復習:DOM要素の作成

createElementはメモリ上に作成します。append、prepend、before、afterはツリーに挿入します。remove()は要素を削除します。DocumentFragmentはパフォーマンス向上のために挿入をまとめて処理します。