이벤트 위임이란, 부모 요소에 이벤트 기능을 추가하여도 자식 요소 까지 이벤트의 기능이 넘어감을 의미함. 다음 예시를 보자.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
<title>JS with Codeit</title>
</head>
<body>
<div id="content">
<h1 id="title">오늘 할 일</h1>
<ul id="list">
<li class="item">자바스크립트 공부</li>
<li class="item">유튜브 시청</li>
<li class="item">저녁 약속</li>
<li class="item">독서</li>
</ul>
</div>
<script src="index.js"></script>
</body>
</html>
.item {
margin: 10px 0;
cursor: pointer;
}
.done {
opacity: 0.5;
text-decoration: line-through;
}
// 이벤트 위임 - 부모 요소에 이벤트를 설정해도 자식 요소로 간다.
const list = document.querySelector('#list');
list.addEventListener('click', function(e) {
e.target.classList.toggle('done');
});
// 태그 추가
const li = document.createElement('li');
li.classList.add('item');
li.textContent = '일기 쓰기';
list.append(li);
자식 요소 쪽이 아닌 다른 곳으로 클릭해도 전체적으로 이벤트 기능이 적용이 되어서 정확하게 클릭하지 않으면 문제가 발생할 수 도 있음.
참고로 태그 추가에도 이벤트 기능을 적용시키기 위해서 개별적으로 자식 태그에 이벤트를 일일이 설정하기 보다는
이벤트 위임
기능을 이용해서 이벤트를 설정해놓은 것이다.
// 이벤트 위임 - 부모 요소에 이벤트를 설정해도 자식 요소로 간다.
const list = document.querySelector('#list');
list.addEventListener('click', function(e) {
//if(e.target.tagName == 'li')
if ( e.target.classList.contains('item')) {
e.target.classList.toggle('done');
}
});
// 태그 추가
const li = document.createElement('li');
li.classList.add('item');
li.textContent = '일기 쓰기';
list.append(li);
해당 결과물 처럼 정확하게 클릭하지 않으면
done
클래스의 스타일이 적용되지 않
는다.
e.target.tagName 은 해당 이벤트가 발생할 태그명이다.
e.target.classList.contains(class
) 는 해당 이벤트가 발생할 태그에 해당class
가 포함되어있는지 여부를 확인하기 위한 조건이다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>오늘 할 일</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="main">
<h2 class="title">오늘 할 일</h2>
<ul id="to-do-list">
<li class="item">자바스크립트 공부하기</li>
<li class="item">고양이 화장실 청소하기</li>
<li class="item">고양이 장난감 쇼핑하기</li>
</ul>
</div>
<script src="index.js"></script>
</body>
</html>
body {
margin: 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
}
.main {
width: 350px;
margin: 40px;
padding: 30px 0;
background-color: #FCFCFC;
box-shadow: -5px -5px 20px #DFDFDF, 5px 5px 20px #BABECC;
border-radius: 8px;
text-align: center;
}
.title {
margin: 15px auto;
font-size: 30px;
font-weight: 600;
color: #9600FF;
}
#to-do-list {
width: 280px;
margin: 0 auto 15px;
padding: 0;
list-style: none;
}
#to-do-list li {
display: flex;
align-items: center;
justify-content: center;
width: 90%;
height: 40px;
margin: 8px auto 15px;
border-bottom: 1px solid #9600FF;
cursor: pointer;
}
.done {
opacity: 0.5;
text-decoration: line-through;
}
const toDoList = document.querySelector('#to-do-list');
// 1. updateToDo 함수를 완성해 주세요.
function updateToDo(event) {
if (event.target.classList.contains('item')) {
event.target.classList.toggle('done');
}
}
- ul 태그를 가져온다 (`#to-do-list')
- 함수의 내용은 이벤트 발생 태그에 클래스가 item이 포함되어있다면, 이벤트 발생 태그에
done
클래스명을 추가한다.
// 2. 각 li 태그가 아니라 하나의 태그에만 이벤트 핸들러를 등록해 주세요.
toDoList.addEventListener('click', updateToDo);
- 클릭하면, 해당 함수 실행
// 테스트 코드 const newToDo = document.createElement('li'); newToDo.textContent = '가계부 정리하기'; newToDo.classList.add('item'); toDoList.append(newToDo);
toDoList.children[2].addEventListener('click', function(e){
e.stopPropagation()
})
> 4. `<li class='item'>가계부정리하기</li>` 생성하여 `<ul>` 태그에 붙인다.
```js
toDoList.children[2].addEventListener('click', function(e){
e.stopPropagation()
})
- 해당 요소의 자식 요소의 이벤트를 발생을 멈추게하는 것이라고 보면 된다.