JavaScript

DOM操作

JavaScript

要素の取得、イベント、操作

DOM要素の取得

querySelector、getElementById など

query.js javascript
// 1要素取得
document.getElementById('header');
document.querySelector('.card');           // CSSセレクター(最初の1つ)
document.querySelector('#nav > a.active');

// 複数要素取得(NodeList)
document.querySelectorAll('.item');
document.querySelectorAll('ul > li:not(.hidden)');

// 関係ナビゲーション
const el = document.querySelector('.container');
el.parentElement;
el.children;
el.firstElementChild;
el.lastElementChild;
el.nextElementSibling;
el.previousElementSibling;

// 祖先を遡る
el.closest('.section');   // 条件に合う最近の祖先
el.matches('.active');    // 要素が条件に合うか

// NodeList を配列に変換
const items = [...document.querySelectorAll('.item')];
const items = Array.from(document.querySelectorAll('.item'));

DOM操作

要素の作成・追加・削除・変更

manipulation.js javascript
// 要素の作成
const card = document.createElement('div');
card.className = 'card';
card.textContent = 'Hello';              // テキストのみ(XSS安全)
card.innerHTML = '<strong>Hi</strong>';  // HTML(XSS注意)

// 要素の追加
parent.appendChild(card);               // 末尾に追加
parent.prepend(card);                   // 先頭に追加
el.insertAdjacentHTML('beforeend', '<li>item</li>');
// 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend'

// クローン
const clone = el.cloneNode(true); // true = 子孫ごとコピー

// 要素の削除
el.remove();

// 属性操作
el.setAttribute('data-id', '42');
el.getAttribute('data-id');     // '42'
el.removeAttribute('disabled');
el.toggleAttribute('hidden');
el.dataset.id;                  // data-id 属性

イベント処理

addEventListener、委譲、カスタムイベント

events.js javascript
// 追加と削除
const handler = (e) => console.log(e.target);
el.addEventListener('click', handler);
el.removeEventListener('click', handler);

// オプション
el.addEventListener('click', handler, {
    once:    true,  // 1回だけ
    passive: true,  // スクロール最適化
    capture: true,  // キャプチャフェーズ
});

// イベントオブジェクト
el.addEventListener('click', (e) => {
    e.target;            // 発生元要素
    e.currentTarget;     // リスナー設置要素
    e.preventDefault();  // デフォルト動作キャンセル
    e.stopPropagation(); // バブリング停止
});

// イベント委譲(動的要素に有効)
document.querySelector('#list').addEventListener('click', (e) => {
    if (e.target.matches('.item')) {
        console.log('クリック:', e.target.dataset.id);
    }
});

// カスタムイベント
const event = new CustomEvent('user:login', {
    detail: { userId: 42 },
    bubbles: true,
});
el.dispatchEvent(event);
window.addEventListener('user:login', e => console.log(e.detail));

スタイルとクラス操作

classList、style、サイズ取得

styles.js javascript
// classList
el.classList.add('active', 'visible');
el.classList.remove('hidden');
el.classList.toggle('expanded');
el.classList.toggle('dark', isDark);  // 条件付き
el.classList.contains('active');      // true/false
el.classList.replace('old', 'new');

// インラインスタイル
el.style.color = 'red';
el.style.backgroundColor = '#f0fdf4'; // キャメルケース
el.style.setProperty('--my-var', '#10b981'); // CSS変数

// 計算済みスタイルの取得
const styles = getComputedStyle(el);
styles.getPropertyValue('color');
styles.getPropertyValue('--my-var');

// 要素のサイズと位置
el.getBoundingClientRect(); // { top, left, width, height }
el.offsetWidth;             // マージン除く幅
el.clientWidth;             // パディング含む幅

// Intersection Observer
const observer = new IntersectionObserver(entries => {
    entries.forEach(e => {
        if (e.isIntersecting) e.target.classList.add('visible');
    });
}, { threshold: 0.1 });
observer.observe(el);