DOM操作
JavaScript
要素の取得、イベント、操作
DOM要素の取得
querySelector、getElementById など
// 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操作
要素の作成・追加・削除・変更
// 要素の作成
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、委譲、カスタムイベント
// 追加と削除
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、サイズ取得
// 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);