유명한 담벼락

Javascript : 이벤트 핸들러

by 담담이담

 

1. 이벤트 핸들러 등록하기

1) 프로퍼티 사용하기 

onclick 프로퍼티는 새로운 값을 할당하면,

기존의 값을 덮어쓰기에

기존 값을 유지하면서 추가적으로 핸들러를 추가하기 어려움

뿐만 아니라 핸들러에 리턴값이 존재할 때 관리하기 어려우며

여러 개의 핸들러를 다루기도 어려움

 

따라서 addEventListener를 사용하는 게 권장됨 

 

2) addEventListener

파라미터로 이벤트 타입을 문자열로,

번째 파라미터로 이벤트 핸들러를 전달하면된다.

 

// 이벤트 등록하기
let btn = document.querySelector('#myBtn');

function event1() {
	console.log('Hi Codeit!');
}

function event2() {
	console.log('Hi again!');
}

// elem.addEventListener(event, handler)
btn.addEventListener('click', event1);
btn.addEventListener('click', event2);

// elem.removeEventListener(event, handler)
btn.removeEventListener('click', event2);

removeEventListener를 사용할 때는 

addEventListener로 이벤트를 등록했을 때 사용한 핸들러의 이름과

removeEventListener로 삭제하려는 핸들러의 이름이 같아야한다.

 

2. 이벤트 객체

// 이벤트 객체 (Event Object)
const myInput = document.querySelector('#myInput');
const myBtn = document.querySelector('#myBtn');

function printEvent(event) {
  console.log(event);
	event.target.style.color = 'red';
}

myInput.addEventListener('keydown', printEvent);
myBtn.addEventListener('click', printEvent);

이벤트가 발생하면, 이벤트와 관련된 객체가 자동으로 만들어진다.

사실 이벤트 핸들러의 첫 번째 파라미터에는

항상 이벤트 객체가 전달된다.

 

 

 

이벤트 객체 안에는 정말 많은 프로퍼티들이 존재하는데,

자주 사용되는 프로퍼티는 target과 type이다.

 

type - 이벤트의 타입(click, keydown, focus 등)

target -  이벤트가 발생한 dom 요소(여기서는 #myInput)

 

3. 이벤트 버블링

1) 의미 

하나의 요소에 이벤트가 발생하면,

그 요소에 할당된 이벤트 핸들러가 동작하고 난 뒤

 

최상단인 윈도우 객체를 만날 때까지

부모 요소에 같은 타입의 이벤트가 존재한다면

그 또한 작동한다.

 

2) 주의할 점 

버블링이 발생할 때 

 target은 항상

이벤트의 발생되기 시작한 요소를 가르키고 있다.

 

만약, 지금 실행 중인 핸들러가 등록된 요소가 궁금하다면,

이벤트 객체의 currentTarget 프로퍼티를 사용하면 된다.

 

 

3) 버블링을 멈추고 싶다면?

이벤트 객체의 stopPropagation 프로퍼티를 사용

하지만 가급적 버블링을 막지 않는 게 좋음

상위 요소에 이벤트를 만들고

그 요소의 하위 요소에도 전부 적용하고자 할 경우들이 많기 때문이다

 

 

4. 이벤트 캡쳐링

1) 의미

이벤트 하나가 발생하면

가장 상위의 window 객체부터 이벤트가 발생한 객체까지

이벤트를 탐색하는 과정을 캡쳐링이라고 한다.

 

3 & 4 이벤트의 흐름

1) 단계별 흐름

1. 캡처링 단계: 이벤트가 하위 요소로 전파되는 단계

2. 타깃 단계: 이벤트가 실제 타깃 요소에 전달되는 단계

3. 버블링 단계: 이벤트가 상위 요소로 전파되는 단계

 

 

2) 그림으로 살펴보기

 

이벤트가 발생하면 가장 먼저 window 객체에서부터 target 까지 이벤트 전파가 일어난다. (캡쳐링 단계)

그리고 나서 타깃에 도달하면 타깃에 등록된 이벤트 핸들러가 동작하고, (타깃 단계)

이후 다시 window 객체로 이벤트가 전파된다. (버블링 단계)

 

 

3) 캡쳐링과 버블링 차이

캡쳐링 - 이벤트 발생 X가 디폴트 

버블링 - 이벤트 발생 O가 디폴트

 

 

캡쳐링일 때 이벤트 핸들러를 동작시키려면 

아래와 같이 

addEventListener에 세번째 파라미터에

true 또는 { capture:true }를 전달하면 된다.

 

캡쳐링과 버블링을 코드로 이해하고 싶다면

아래 코드를 실행시켜보세요!

 

See the Pen 캡쳐링&버블링 by youdame (@youdame) on CodePen.

 

5. 이벤트 위임

아래의 코드를 보면

#list라는 선택자를 가진 요소의 자식 요소인 item들에게

이벤트리스너를 이용해

모두 done이라는 class를 

적용시켰다. 

 

See the Pen 이벤트 캡쳐링, 버블링 by youdame (@youdame) on CodePen.

 

 

 

 

문제점

for문이 동작하고 난 뒤 추가된

'일기쓰기'에는 이벤트가 등록되지 않음

 

=> 그럼 매번 추가할 때마다 이벤트 핸들러를 새로 등록해야하나?

 


NO!

이벤트 버블링을 이용하자.

부모 요소인 리스트에 이벤트 핸들러를 하나만 등록해줘도

모든 자식 요소 item들에게도 적용되게 할 수 있음

 

 

See the Pen 이벤트 위임-2 by youdame (@youdame) on CodePen.

 

But.. 또 다른 문제 

 

자식 요소를 제외한 부모 요소만 클릭해도 

이벤트 핸들러가 적용됨

 

따라서 이벤트 위임을 할 때는 

정확히 원하는 위치에서 의도한 동작이 일어나게끔

따로 처리를 해줘야함

 

See the Pen 이벤트 위임-3 by youdame (@youdame) on CodePen.

 

여기에서는 

 

 

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');
	}
});

target property의 tagName이 LI인지 확인하거나

target의 classList가 item을 포함하고 있는지를 확인함으로써

이를 구현했다.

 

 

 

 

블로그의 정보

유명한 담벼락

담담이담

활동하기