6. 이벤트 전파(event propagation)
<body>
<ul id="fruits">
<li id="apple">Apple</li>
<li id="banana">Banana</li>
<li id="orange">Orange</li>
</ul>
<script>
const $fruits = document.getElementById("fruits");
$fruits.addEventListener('click', e => {
console.log(`이벤트 단계: ${e.eventPhase}`);
console.log(`이벤트 타깃: ${e.target}`);
console.log(`커런트 타깃: ${e.currentTarget}`);
});
</script>
</body>
- ul 요소의 두 번째 자식 요소인 li요소를 클릭하면 클릭 이벤트가 발생한다.
- 생성된 이벤트 객체는 이벤트를 발생시킨 DOM 요소인 이벤트 타켓(event target)을 중심으로 DOM 트리를 통해 전파된다.
- 이벤트 전파는 3단계로 구분
① 캡처링 단계(capturing phase) : 이벤트가 상위 요소에서 하위 요소 방향으로 전파
② 타깃 단계(target phase) : 이벤트가 이벤트 타깃에 도달
③ 버블링 단계(bubbling phase) : 이벤트가 하위 요소에서 상위 요소 방향으로 전파
7. 이벤트 위임
- 이벤트 위임(event delegation) : 여러 개의 하위 DOM 요소에 각각 이벤트 핸들러를 등록하는 대신 하나의 상위 DOM 요소에 이벤트 핸들러를 등록하는 방법
- 이벤트 위임을 통해 상위 DOM 요소에 이벤트 핸들러를 등록하면 여러 개의 하위 DOM 요소에 이벤트 핸들러를 등록할 필요가 없다.
<head>
<style>
#fruits {
display: flex;
list-style-type: none;
padding: 0;
}
#fruits li {
width: 100px;
cursor: pointer;
}
#fruits .active {
color: red;
text-decoration: underline;
}
</style>
</head>
<body>
<nav>
<ul id="fruits">
<li id="apple" class="active">Apple</li>
<li id="banana">Banana</li>
<li id="orange">Orange</li>
</ul>
</nav>
<div>선택된 내비게이션 아이템: <em class="msg">apple</em></div>
<script>
const $fruits = document.getElementById("fruits");
const $msg = document.querySelector(".msg");
function activate({ target }){
if(!target.matches('#fruits > li')) return;
[...$fruits.children].forEach($fruits => {
$fruits.classList.toggle('active', $fruit === target);
$msg.textContent = target.id;
});
}
$fruits.onclick = activate;
</script>
</body>
8. DOM 요소의 기본 동작 조작
① DOM 요소의 기본 동작 중단
- 이벤트 객체의 preventDefault 메서드 DOM 요소의 기본 동작을 중단시킨다.
<body>
<a href="https://www.google.com">GO!</a>
<input type="checkbox">
<script>
document.querySelector('a').onclick = e => {
e.preventDefault();
};
document.querySelector('input[type=checkbox]').onclick = e => {
e.preventDefault();
};
</script>
</body>
② 이벤트 전파 방지
- 이벤트 객체의 stopPropagation 메서드는 하위 DOM 요소의 이벤트를 개별적으로 처리하기 위해 이벤트 전파를 중단시킨다.
<body>
<div class="container">
<button class="btn1">Button 1</button>
<button class="btn2">Button 2</button>
<button class="btn3">Button 3</button>
</div>
<script>
document.querySelector(".container").onclick = ({ target }) => {
if (!target.matches(".container > button")) return;
target.style.color = "red";
};
document.querySelector(".btn2").onclick = e => {
e.stopPropagation();
e.target.styled.color = "blue";
}
</script>
</body>
- 하위 요소 중에서 btn2 요소는 자체적으로 이벤트를 처리한다.
- btn2 요소는 자신이 발생시킨 이벤트가 전파되는 것을 중단하여 자신에게 바인딩된 이벤트 핸들러만 실행되도록 한다.
9. 이벤트 핸들러 내부의 this
① 이벤트 핸들러 어트리뷰트 방식
<body>
<button onclick="handleClick()">Click me!</button>
<script>
function handleClick(button){
console.log(button);
console.log(this);
}
</script>
</body>
② 이벤트 핸들러 프로퍼티 방식과 addEventListener 메서드 방식