event delegation은 이벤트를 위임하여 부모에게 전달하는 것을 말합니다.
하트를 클릭했을 때 하트 대상에게 on 클래스를 주어서 하트에 불이 들어오게 했던 것을 기억하실 겁니다. 하지만 클래스를 주어야 할 요소의 개수가 많아지게 되면 어떻게 될까요? 비효율적으로 모든 요소들에 이벤트를 반복적으로 추가하여야 할 것입니다. 물론 반복문을 사용할 수도 있겠지만, 이보다 효율적인 방법이 event delegation을 활용하는 것입니다.
게시물 부분을 보시면 하트, 댓글, 공유, 게시 버튼 등 이벤트를 추가해야할 요소가 많은 것을 볼 수 있습니다. 그래서 이벤트를 이들을 모두 포함하는 컨텐츠 박스에 추가하고, 이벤트를 위임하는 방법을 event delegation이라고 보면 됩니다.
그러면 기존의 이벤트를 수정하여 event delegation으로 수정하고, 북마크 기능 또한 추가해보도록 하겠습니다.
파일명 : js/main.js
const heart = document.querySelector( '.heart_btn'); // 하트 요소 부분을 선택해서 가져옴
const header = document.querySelector('#header');
const sidebox = document.querySelector( '.side_box');
// SelectorAll을 활용해 모든 요소를 가져옴
const variableWidth = document.querySelectorAll(".contents_box .contents");
**const deligation = document.querySelector(".contents_box");**
/* heart.addEventListener('click', function(){
console.log('hit');
heart.classList.toggle('on'); // 하트를 클릭하면 .on 클래스를 추가
}); */
**function deligationFunc(e){**
**let elem = e.target; // 클릭한 요소 가져오기**
**// console.log(e.target);**
**// console.log(elem);**
**// 잘못 클릭한 경우**
**while(!elem.getAttribute('data-name')){**
**// elem의 부모를 찾음**
**elem = elem.parentNode;**
**if(elem.nodeName ==='BODY'){ // body까지 이벤트가 없는 경우**
**elem=null;**
**return;**
**} // data-name을 가진 속성을 찾을때까지 부모에게 접근을 반복**
**}**
**if(elem.matches('[data-name="heartbeat"]')){**
**console.log("하트!");**
**}else if(elem.matches('[data-name="bookmark"]')){**
**console.log("북마크!");**
**}else if(elem.matches('[data-name="share"]')){**
**console.log("공유!");**
**}if(elem.matches('[data-name="more"]')){**
**console.log("더보기!");**
**}**
**elem.classList.toggle('on'); // on 클래스 주기
}**
function resizeFunc(){
**...**
}
**...**
**deligation.addEventListener('click',deligationFunc);**
window.addEventListener('resize',resizeFunc);
window.addEventListener('scroll', scrollFunc); // 스크롤 이벤트 발생 시 scrollFunc 실행
위임받을 이벤트를 찾을 때 까지 부모에게 접근을 반복합니다. 그 뒤 하단의 조건문을 통해서 위임받은 이벤트를 실행하게 됩니다. 이때 index.html
에서 작성했던 data-name 을 활용합니다. 여기서 각각의 data-name을 입력하셔야 합니다.
파일명 : index.html
**...**
<div class="img_section">
<div class="trans_inner">
<div><img src="imgs/img_section/img01.jpg" alt="visual01"></div>
</div>
</div>
<div class="bottom_icons">
<div class="left_icons">
<div class="heart_btn">
<div class="sprite_heart_icon_outline" name="39" **data-name="heartbeat"**></div>
</div>
<div class="sprite_bubble_icon"></div>
<div class="sprite_share_icon" **data-name="share"**></div>
</div>
<div class="right_icon">
<div class="sprite_bookmark_outline" **data-name="bookmark"**></div>
</div>
</div>
**...**
CSS에 .on 부분이 있는지 확인하고, delegation을 통해서 .on 클래스가 추가되는 클래스가 heart_btn이 아닌 .sprite_heart_icon_outline 로 바뀌었기 때문에 수정해주도록 하겠습니다.
파일명 : css/style.css
**...
/*** .heart_btn.on .sprite_heart_icon_outline */**.sprite_heart_icon_outline.on{
background: url('../imgs/background01.png') no-repeat -26px -261px;
}**
.contents .likes{
padding: 5px 20px;
color:#262626;
}
**...**
.sprite_bookmark_outline{
display: inline-block;
background: url('../imgs/background01.png') no-repeat -237px -286px;
width: 19px;
height: 24px;
}
**.sprite_bookmark_outline.on{
background: url('../imgs/background01.png') no-repeat -159px -286px;
width: 19px;
height: 24px;
}**
**...**