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;
}**

**...**