[TIL]이벤트 흐름과 currentTarget

최영준·2022년 10월 19일
1
post-thumbnail

흐름

브라우저 화면에서 이벤트가 발생하면 브라우저는 가장 먼저 이벤트 대상을 찾기 시작.

브라우저가 이벤트 대상을 찾아갈 때는 가장 상위의 window 객체부터 document, body 순으로 DOM 트리를 따라 내려갑니다. 이를 캡처링 단계라고 합니다.

이때 이벤트 대상을 찾아가는 과정에서 브라우저는 중간에 만나는 모든 캡처링 이벤트 리스너를 실행시킵니다. 그리고 이벤트 대상을 찾고 캡처링이 끝나면 이제 다시 DOM 트리를 따라 올라가며 만나는 모든 버블링 이벤트 리스너를 실행합니다. 이를 이벤트 버블링 단계라고 합니다.

그리고 이러한 과정에서 이벤트 리스너가 차례로 실행되는것을 이벤트 전파(event propagation)라고 합니다.

이벤트 등록

웹 애플리케이션에서 사용자의 입력을 받기 위해 필요한 기능.

<button>add one item</button>
var button = document.querySelector('button');
button.addEventListener('click', addItem);
function addItem(event) {
	console.log(event);
}

add one item이라는 버튼을 만들어 클릭 시 addItem이라는 함수를 실행시키는 코드.
버튼을 클릭하고 나면 addItem 함수가 실행되고 addItem 함수에 event 인자가 넘어옵니다.
event 인자를 콘솔에 출력해보면 이벤트와 관련된 정보를 확인할 수 있습니다.

찍어보았습니다.
콘솔 창에서 우리가 봐야할 코드가 이 부분이 맞는지는 모르겠으나, 이벤트와 관련된 정보를 볼 수 있다는 점이 신기!

이벤트 target, currentTarget

부모부터 자식까지 일련의 요소를 모두 타고가며 진행되는 이러한 이벤트의 특징 덕분에 이벤트 객체에는 target, currentTarget 이라는 속성이 존재합니다.

target 속성에는 이벤트가 발생한 진원지의 정보가 담겨 있습니다. target 속성을 통해 이벤트 리스너가 없는 요소의 이벤트가 발생했을 때도 해당 요소에 접근 할 수 있습니다.

currentTarget 속성에는 이벤트 리스너가 연결된 요소가 참조되어 있습니다.

이벤트 위임

앞에서 우리는 이벤트의 흐름을 통해 이벤트 리스너가 없는 요소의 이벤트가 발생했을 때도 해당 요소에 접근 할 수 있다는 것을 알게 되었습니다.

이를 이용해 이벤트 리스너가 없어도 마치 리스너가 있는 것 처럼 사용 할 수 있습니다.

이벤트의 this

이벤트 리스너 함수 내부에서의 this 값은 이벤트가 연결된 노드를 참조합니다.
이는 event.currentTarget 속성의 참조값과 유사합니다.
만약 이벤트 리스너 함수를 화살표 함수로 쓴다면 this 가 가리키는 대상이 달라진다는 점에 유의하세요. 화살표 함수의 this 는 자신을 둘러 싸고 있는 외부 환경의 this 값을 참조합니다.

preventDefault()

브라우저의 기본 이벤트 동작을 취소합니다.
브라우저는 HTML 태그를 통해 여러가지 기능들을 제공합니다. 하지만 때때로 그러한 기능이 방해가 되는 경우가 있습니다.

<!-- 앵커의 기본 동작을 중지 -->
<a href="https://www.naver.com" class="link">네이버 링크입니다만..</a>
<script>
    const link = document.querySelector('.link');
    link.addEventListener('click', (event) => {
        console.log('clicked');
        event.preventDefault();
    })
</script>
<!-- submit 의 기본 동작을 중지 -->
<form action="">
    <button type="submit" class="submit">제출</button>
</form>
<script>
    const submit = document.querySelector('.submit');
    submit.addEventListener('click', (event) => {
        console.log('clicked');
        event.preventDefault();
    })
</script>

이렇듯 종종 브라우저의 기본 동작을 중지하고 자바스크립트를 통해 기능을 처리하고자 할때 사용합니다.

stopPropagation()

앞에서 우리는 preventDefault를 통해 브라우저의 기본 이벤트 동작을 취소해봤습니다. 하지만 이때 우리가 앞에서 배웠던 이벤트 흐름, 즉 이벤트 전파(이벤트 프로파게이션)를 막지는 못합니다.

<form action="">
	<button type="submit" class="submit">제출</button>
</form>
<script>
	const submit = document.querySelector('.submit');
	submit.addEventListener('click', (event) => {
	    console.log('clicked');
	    event.preventDefault();
			// event.stopPropagation();
	});
	document.body.addEventListener('click', () => {
	    console.log('event still alive!');
	});

이때 만약 이벤트 전파를 막고 싶다면 event.stopPropagation() 코드를 추가합니다.
  // IE에서 for of 문 작성 불가
        // for (const item of txts) {
        //     item.addEventListener('click', () => {
        //         alert(event.target.textContent.slice(0, -2));
        //     })
        // }
        // IE는 nodelist 에 forEach 문 작성 불가
        // txts.forEach(item => {
        //     item.addEventListener('click', () => {
        //         alert(event.target.textContent.slice(0, -2));
        //     })
        // })
</script>
profile
기록하는 습관을 들여보자!

1개의 댓글

comment-user-thumbnail
2022년 10월 24일

잘 보고 갑니다

답글 달기