イベントデリゲーションはJavaScriptの重要な最適化手法で、イベントバブリングの原理を利用して実装されます。イベントバブリングとは、深いノードから上位ノードへとイベントが伝播していく仕組みです。例えばdiv>ul>li>aという構造で、a要素にクリックイベントを設定すると、a→li→ul→divの順でイベントが伝播します。
イベントデリゲーションの主な利点は2つあります:
1. コードの簡潔化
2. パフォーマンスの向上
基本的な実装例を見てみましょう:
<ul id="container">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<script>
const container = document.getElementById('container');
container.addEventListener('click', function(event) {
if(event.target.tagName === 'LI') {
console.log('List item clicked');
}
});
</script>
この方法では、各li要素に個別にイベントリスナーを設定する代わりに、親要素のulに1つのリスナーを設定しています。これにより、DOM操作が大幅に減少します。
異なる操作が必要な場合の実装例:
<div id="controlPanel">
<button id="btnCreate">作成</button>
<button id="btnDelete">削除</button>
<button id="btnUpdate">更新</button>
</div>
<script>
const panel = document.getElementById('controlPanel');
panel.addEventListener('click', function(e) {
const target = e.target;
switch(target.id) {
case 'btnCreate':
console.log('作成処理');
break;
case 'btnDelete':
console.log('削除処理');
break;
case 'btnUpdate':
console.log('更新処理');
break;
}
});
</script>
動的に追加される要素への対応:
<button id="addBtn">追加</button>
<ul id="dynamicList">
<li>項目1</li>
<li>項目2</li>
</ul>
<script>
const list = document.getElementById('dynamicList');
const addBtn = document.getElementById('addBtn');
let counter = 2;
list.addEventListener('mouseover', function(e) {
if(e.target.tagName === 'LI') {
e.target.style.backgroundColor = '#ff0000';
}
});
list.addEventListener('mouseout', function(e) {
if(e.target.tagName === 'LI') {
e.target.style.backgroundColor = '#ffffff';
}
});
addBtn.addEventListener('click', function() {
counter++;
const newItem = document.createElement('li');
newItem.textContent = `項目${counter}`;
list.appendChild(newItem);
});
</script>
複雑な構造への対応方法:
<ul id="complexList">
<li><p>テキスト1</p></li>
<li><div>テキスト2</div></li>
<li><span>テキスト3</span></li>
</ul>
<script>
const complexList = document.getElementById('complexList');
complexList.addEventListener('click', function(e) {
let element = e.target;
while(element !== complexList) {
if(element.tagName === 'LI') {
console.log('リストアイテムがクリックされました');
break;
}
element = element.parentNode;
}
});
</script>